home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / Ang261Lib.lha / src / moria1.c < prev    next >
C/C++ Source or Header  |  1994-10-22  |  75KB  |  2,840 lines

  1. /*
  2.  * moria1.c: misc code, mainly to handle player movement, inventory, etc. 
  3.  *
  4.  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke 
  5.  *
  6.  * This software may be copied and distributed for educational, research, and
  7.  * not for profit purposes provided that this copyright and statement are
  8.  * included in all such copies. 
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <ctype.h>
  13.  
  14. #include "constant.h"
  15. #include "config.h"
  16. #include "types.h"
  17. #include "externs.h"
  18. #include "monster.h"
  19.  
  20. #ifdef USG
  21. #ifndef ATARIST_MWC
  22. #include <string.h>
  23. #else
  24. char *strcat();
  25. int   strlen();
  26.  
  27. #endif
  28. #else
  29. #include <strings.h>
  30. #endif
  31.  
  32. /* Lets do all prototypes correctly.... -CWS */
  33. #ifndef NO_LINT_ARGS
  34. #ifdef __STDC__
  35. static void inven_screen(int);
  36. static char map_roguedir(int);
  37. static void sub1_move_light(int, int, int, int);
  38. static void sub3_move_light(int, int, int, int);
  39. static int see_wall(int, int, int);
  40. static int see_nothing(int, int, int);
  41. #else
  42. static void inven_screen();
  43. static char map_roguedir();
  44. static void sub1_move_light();
  45. static void sub3_move_light();
  46. static int  see_wall();
  47. static int  see_nothing();
  48. #endif
  49. #endif
  50.  
  51.  
  52. /* Changes speed of monsters relative to player        -RAK-
  53.  * Note: When the player is sped up or slowed down, I simply change the
  54.  * speed of all the monsters.  This greatly simplified the logic.
  55.  *****
  56.  * No LONGER!  A change in player speed only affect player's speed.  The new
  57.  * code in movement_rate() allows monsters to have attacks in correct
  58.  * proportions, and still uses only int math -CFT 
  59.  */
  60. void 
  61. change_speed(num)
  62. register int num;
  63. {
  64.     py.flags.speed += num;
  65.     py.flags.status |= PY_SPEED;
  66. }
  67.  
  68.  
  69. /* Player bonuses                    -RAK-     */
  70. /* When an item is worn or taken off, this re-adjusts the player
  71.  * bonuses.  Factor=1 : wear; Factor=-1 : removed  
  72.  *****
  73.  * Only calculates properties with cumulative effect.  Properties that depend
  74.  * on everything being worn are recalculated by calc_bonuses() -CJS - 
  75.  */
  76. void 
  77. py_bonuses(t_ptr, factor)
  78. register inven_type *t_ptr;
  79. register int         factor;
  80. {
  81.     register int i, amount;
  82.  
  83.     amount = t_ptr->p1 * factor;
  84.     if (t_ptr->flags & TR_STATS) {
  85.     for (i = 0; i < 6; i++)
  86.         if ((1 << i) & t_ptr->flags)
  87.         bst_stat(i, amount);
  88.     }
  89.     if (TR_SEARCH & t_ptr->flags) {
  90.     py.misc.srh += amount;
  91.     py.misc.fos -= amount;
  92.     }
  93.     if (TR_STEALTH & t_ptr->flags)
  94.     py.misc.stl += amount;
  95.     if (TR_SPEED & t_ptr->flags) {
  96.     if ((t_ptr->tval == TV_RING) &&
  97.         !stricmp("Speed",
  98.              object_list[t_ptr->index].name) &&
  99.         (t_ptr->p1 > 0))
  100.         if ((inventory[INVEN_RIGHT].tval == TV_RING) &&
  101.         !stricmp("Speed",
  102.              object_list[inventory[INVEN_RIGHT].index].name) &&
  103.         (inventory[INVEN_RIGHT].p1 > 0) &&
  104.         (inventory[INVEN_LEFT].tval == TV_RING) &&
  105.         !stricmp("Speed",
  106.              object_list[inventory[INVEN_LEFT].index].name) &&
  107.         (inventory[INVEN_RIGHT].p1 > 0))
  108.         return;
  109.     change_speed(-amount);
  110.     }
  111.     if (TR_INFRA & t_ptr->flags)
  112.     py.flags.see_infra += amount;
  113. }
  114.  
  115. /* Recalculate the effect of all the stuff we use.          -CJS- */
  116. /* Also initialise race intrinsics    SM */
  117. void 
  118. calc_bonuses()
  119. {
  120.     register int32u        item_flags;
  121.     register int32u        item_flags2;
  122.     int                    old_dis_ac;
  123.     register struct flags *p_ptr;
  124.     register struct misc  *m_ptr;
  125.     register inven_type   *i_ptr;
  126.     register int           i;
  127.  
  128.     p_ptr = &py.flags;
  129.     m_ptr = &py.misc;
  130.     if (p_ptr->slow_digest)
  131.     p_ptr->food_digested++;
  132.     if (p_ptr->regenerate)
  133.     p_ptr->food_digested -= 3;
  134.     if (py.misc.prace == 9)
  135.     p_ptr->see_inv = TRUE;
  136.     else
  137.     p_ptr->see_inv = FALSE;
  138.     p_ptr->teleport = FALSE;
  139.     if (py.misc.prace == 4)
  140.     p_ptr->free_act = TRUE;
  141.     else
  142.     p_ptr->free_act = FALSE;
  143.     p_ptr->slow_digest = FALSE;
  144.     p_ptr->aggravate = FALSE;
  145.     if (py.misc.prace == 7)
  146.     p_ptr->sustain_str = TRUE;
  147.     else
  148.     p_ptr->sustain_str = FALSE;
  149.     p_ptr->sustain_int = FALSE;
  150.     p_ptr->sustain_wis = FALSE;
  151.     if (py.misc.prace == 8)
  152.     p_ptr->sustain_con = TRUE;
  153.     else
  154.     p_ptr->sustain_con = FALSE;
  155.     if (py.misc.prace == 3)
  156.     p_ptr->sustain_dex = TRUE;
  157.     else
  158.     p_ptr->sustain_dex = FALSE;
  159.     p_ptr->sustain_chr = FALSE;
  160.     p_ptr->fire_resist = FALSE;
  161.     p_ptr->acid_resist = FALSE;
  162.     p_ptr->cold_resist = FALSE;
  163.     p_ptr->regenerate = FALSE;
  164.     p_ptr->lght_resist = FALSE;
  165.     if (py.misc.prace == 9)
  166.     p_ptr->ffall = TRUE;
  167.     else
  168.     p_ptr->ffall = FALSE;
  169.     p_ptr->poison_resist = FALSE;
  170.     p_ptr->hold_life = FALSE;
  171.     p_ptr->telepathy = FALSE;
  172.     p_ptr->fire_im = FALSE;
  173.     p_ptr->acid_im = FALSE;
  174.     p_ptr->poison_im = FALSE;
  175.     p_ptr->cold_im = FALSE;
  176.     p_ptr->light_im = FALSE;
  177.     p_ptr->light = FALSE;
  178.     p_ptr->confusion_resist = FALSE;
  179.     p_ptr->sound_resist = FALSE;
  180.     if (py.misc.prace == 2)
  181.     p_ptr->light_resist = TRUE;
  182.     else
  183.     p_ptr->light_resist = FALSE;
  184.     if (py.misc.prace == 6)
  185.     p_ptr->dark_resist = TRUE;
  186.     else
  187.     p_ptr->dark_resist = FALSE;
  188.     p_ptr->chaos_resist = FALSE;
  189.     p_ptr->disenchant_resist = FALSE;
  190.     p_ptr->shards_resist = FALSE;
  191.     p_ptr->nexus_resist = FALSE;
  192.     if (py.misc.prace == 5)
  193.     p_ptr->blindness_resist = TRUE;
  194.     else
  195.     p_ptr->blindness_resist = FALSE;
  196.     p_ptr->nether_resist = FALSE;
  197.     p_ptr->fear_resist = FALSE;
  198.  
  199.     old_dis_ac = m_ptr->dis_ac;
  200.     m_ptr->ptohit = tohit_adj();   /* Real To Hit   */
  201.     m_ptr->ptodam = todam_adj();   /* Real To Dam   */
  202.     m_ptr->ptoac = toac_adj();       /* Real To AC    */
  203.     m_ptr->pac = 0;           /* Real AC         */
  204.     m_ptr->dis_th = m_ptr->ptohit; /* Display To Hit        */
  205.     m_ptr->dis_td = m_ptr->ptodam; /* Display To Dam        */
  206.     m_ptr->dis_ac = 0;           /* Display AC         */
  207.     m_ptr->dis_tac = m_ptr->ptoac; /* Display To AC        */
  208.     for (i = INVEN_WIELD; i <= INVEN_LIGHT; i++) {
  209.     i_ptr = &inventory[i];
  210.     if (i_ptr->tval != TV_NOTHING) {
  211.         if ((TR_CURSED & i_ptr->flags) == 0) {
  212.         m_ptr->pac += i_ptr->ac;
  213.         m_ptr->dis_ac += i_ptr->ac;
  214.         }
  215.         m_ptr->ptohit += i_ptr->tohit;
  216.         if (i_ptr->tval != TV_BOW)                /* Bows can't damage. -CJS- */
  217.         m_ptr->ptodam += i_ptr->todam;
  218.         m_ptr->ptoac += i_ptr->toac;
  219.         if (known2_p(i_ptr)) {
  220.         m_ptr->dis_th += i_ptr->tohit;
  221.         if (i_ptr->tval != TV_BOW)
  222.             m_ptr->dis_td += i_ptr->todam;    /* Bows can't damage. -CJS- */
  223.         m_ptr->dis_tac += i_ptr->toac;
  224.         }
  225.     }
  226.     }
  227.  
  228.     if (py.misc.pclass == 2) {
  229.     i_ptr = &inventory[INVEN_WIELD];
  230.     if (!(i_ptr->flags2 & TR_BLESS_BLADE) && /* blessed blade == no penalty -CWS */
  231.         (i_ptr->tval == TV_SWORD || i_ptr->tval == TV_POLEARM)) {
  232.         m_ptr->ptohit -= 2;
  233.         m_ptr->ptodam -= 2;
  234.         m_ptr->dis_th -= 2;
  235.         m_ptr->dis_td -= 2;
  236.     }
  237.     }
  238.     if (weapon_heavy)
  239.     m_ptr->dis_th += (py.stats.use_stat[A_STR] * 15 -
  240.               inventory[INVEN_WIELD].weight);
  241.  
  242. /* don't forget stun adj, or we'll get incorrect values... -CFT */
  243.     if (p_ptr->stun > 50) {
  244.     m_ptr->ptohit -= 20;
  245.     m_ptr->dis_th -= 20;
  246.     m_ptr->ptodam -= 20;
  247.     m_ptr->dis_td -= 20;
  248.     } else if (p_ptr->stun > 0) {
  249.     m_ptr->ptohit -= 5;
  250.     m_ptr->dis_th -= 5;
  251.     m_ptr->ptodam -= 5;
  252.     m_ptr->dis_td -= 5;
  253.     }
  254. /* Add in temporary spell increases     */
  255. /*
  256.  * these changed from pac to ptoac, since mana now affected by high pac (to
  257.  * sim. encumberence), and these really should be magical bonuses -CFT 
  258.  */
  259.     if (p_ptr->status & PY_INVULN) {
  260.     m_ptr->ptoac += 100;
  261.     m_ptr->dis_tac += 100;
  262.     }
  263.     if (p_ptr->status & PY_BLESSED) {    /* changed to agree w/ code in
  264.                      * dungeon()... -CFT */
  265.     m_ptr->ptoac += 5;
  266.     m_ptr->dis_tac += 5;
  267.     m_ptr->ptohit += 10;
  268.     m_ptr->dis_th += 10;
  269.     }
  270.     if (p_ptr->shield > 0) {
  271.     m_ptr->ptoac += 50;
  272.     m_ptr->dis_tac += 50;
  273.     }
  274.     if (p_ptr->detect_inv > 0)
  275.     p_ptr->see_inv = TRUE;
  276.     if (p_ptr->status & PY_HERO) { /* now agrees w/ code in dungeon() -CFT */
  277.     m_ptr->ptohit += 12;
  278.     m_ptr->dis_th += 12;
  279.     }
  280.     if (p_ptr->status & PY_SHERO) {/* now agrees w/ code in dungeon() -CFT */
  281.     m_ptr->ptohit += 24;
  282.     m_ptr->dis_th += 24;
  283.     m_ptr->ptoac -= 10;       /* berserk, so not being careful... -CFT */
  284.     m_ptr->dis_tac -= 10;
  285.     }
  286.     m_ptr->dis_ac += m_ptr->dis_tac;    /* this moved from above, so it will
  287.                      * show ac adjustments from spells...
  288.                      * -CFT */
  289.  
  290. /* can't print AC here because might be in a store */
  291.     p_ptr->status |= PY_ARMOR;       /* This was in an if, but I want to be
  292.                     * sure ac is shown properly... -CFT */
  293.  
  294.     item_flags = 0L;
  295.     i_ptr = &inventory[INVEN_WIELD];
  296.     for (i = INVEN_WIELD; i <= INVEN_LIGHT; i++) {
  297.     item_flags |= i_ptr->flags;
  298.     i_ptr++;
  299.     }
  300.     item_flags2 = 0L;
  301.     i_ptr = &inventory[INVEN_WIELD];
  302.     for (i = INVEN_WIELD; i <= INVEN_LIGHT; i++) {
  303.     item_flags2 |= i_ptr->flags2;
  304.     i_ptr++;
  305.     }
  306.  
  307.     if (TR_SLOW_DIGEST & item_flags)
  308.     p_ptr->slow_digest = TRUE;
  309.     if (TR_AGGRAVATE & item_flags)
  310.     p_ptr->aggravate = TRUE;
  311.     if (TR_TELEPORT & item_flags)
  312.     p_ptr->teleport = TRUE;
  313.     if (TR_REGEN & item_flags)
  314.     p_ptr->regenerate = TRUE;
  315.     if (TR_RES_FIRE & item_flags)
  316.     p_ptr->fire_resist = TRUE;
  317.     if (TR_RES_ACID & item_flags)
  318.     p_ptr->acid_resist = TRUE;
  319.     if (TR_RES_COLD & item_flags)
  320.     p_ptr->cold_resist = TRUE;
  321.     if (TR_POISON & item_flags)
  322.     p_ptr->poison_resist = TRUE;
  323.     if (TR_HOLD_LIFE & item_flags2)
  324.     p_ptr->hold_life = TRUE;
  325.     if (TR_TELEPATHY & item_flags2)
  326.     p_ptr->telepathy = TRUE;
  327.     if (TR_IM_FIRE & item_flags2)
  328.     p_ptr->fire_im = TRUE;
  329.     if (TR_IM_ACID & item_flags2)
  330.     p_ptr->acid_im = TRUE;
  331.     if (TR_IM_COLD & item_flags2)
  332.     p_ptr->cold_im = TRUE;
  333.     if (TR_IM_LIGHT & item_flags2)
  334.     p_ptr->light_im = TRUE;
  335.     if (TR_IM_POISON & item_flags2)
  336.     p_ptr->poison_im = TRUE;
  337.     if (TR_LIGHT & item_flags2)
  338.     p_ptr->light = TRUE;
  339.     if (TR_FREE_ACT & item_flags)
  340.     p_ptr->free_act = TRUE;
  341.     if (TR_SEE_INVIS & item_flags)
  342.     p_ptr->see_inv = TRUE;
  343.     if (TR_RES_LIGHT & item_flags)
  344.     p_ptr->lght_resist = TRUE;
  345.     if (TR_FFALL & item_flags)
  346.     p_ptr->ffall = TRUE;
  347.     if (TR_RES_CONF & item_flags2)
  348.     p_ptr->confusion_resist = TRUE;
  349.     if (TR_RES_SOUND & item_flags2)
  350.     p_ptr->sound_resist = TRUE;
  351.     if (TR_RES_LT & item_flags2)
  352.     p_ptr->light_resist = TRUE;
  353.     if (TR_RES_DARK & item_flags2)
  354.     p_ptr->dark_resist = TRUE;
  355.     if (TR_RES_CHAOS & item_flags2)
  356.     p_ptr->chaos_resist = TRUE;
  357.     if (TR_RES_DISENCHANT & item_flags2)
  358.     p_ptr->disenchant_resist = TRUE;
  359.     if (TR_RES_SHARDS & item_flags2)
  360.     p_ptr->shards_resist = TRUE;
  361.     if (TR_RES_NEXUS & item_flags2)
  362.     p_ptr->nexus_resist = TRUE;
  363.     if (TR_RES_BLIND & item_flags2)
  364.     p_ptr->blindness_resist = TRUE;
  365.     if (TR_RES_NETHER & item_flags2)
  366.     p_ptr->nether_resist = TRUE;
  367.     if (TR_RES_FEAR & item_flags2)
  368.     p_ptr->fear_resist = TRUE;
  369.  
  370.     i_ptr = &inventory[INVEN_WIELD];
  371.     for (i = INVEN_WIELD; i < INVEN_LIGHT; i++) {
  372.     if (TR_SUST_STAT & i_ptr->flags)
  373.         switch (i_ptr->p1) {
  374.           case 1:
  375.         p_ptr->sustain_str = TRUE;
  376.         break;
  377.           case 2:
  378.         p_ptr->sustain_int = TRUE;
  379.         break;
  380.           case 3:
  381.         p_ptr->sustain_wis = TRUE;
  382.         break;
  383.           case 4:
  384.         p_ptr->sustain_con = TRUE;
  385.         break;
  386.           case 5:
  387.         p_ptr->sustain_dex = TRUE;
  388.         break;
  389.           case 6:
  390.         p_ptr->sustain_chr = TRUE;
  391.         break;
  392.           case 10:           /* :-) ~Ludwig the Hacker!!! */
  393.         p_ptr->sustain_str = TRUE;
  394.         p_ptr->sustain_int = TRUE;
  395.         p_ptr->sustain_wis = TRUE;
  396.         p_ptr->sustain_con = TRUE;
  397.         p_ptr->sustain_dex = TRUE;
  398.         p_ptr->sustain_chr = TRUE;
  399.         break;
  400.           default:
  401.         break;
  402.         }
  403.     i_ptr++;
  404.     }
  405.  
  406.     if (p_ptr->slow_digest)
  407.     p_ptr->food_digested--;
  408.     if (p_ptr->regenerate)
  409.     p_ptr->food_digested += 3;
  410.  
  411.     if (class[py.misc.pclass].spell == MAGE) {
  412.     calc_mana(A_INT);
  413.     } else if (class[py.misc.pclass].spell == PRIEST) {
  414.     calc_mana(A_WIS);
  415.     }
  416. }
  417.  
  418.  
  419. /* Displays inventory items from r1 to r2    -RAK-     */
  420. /*
  421.  * Designed to keep the display as far to the right as possible.  The  -CJS-
  422.  * parameter col gives a column at which to start, but if the display does
  423.  * not fit, it may be moved left.  The return value is the left edge used. 
  424.  */
  425. int 
  426. show_inven(r1, r2, weight, col, test)
  427. register int r1, r2;
  428. int weight, col;
  429. int (*test) ();
  430. {
  431.     register int i, j, k;
  432.     int          total_weight, len, l, lim;
  433.     bigvtype     tmp_val;
  434.     vtype        out_val[23];
  435.  
  436.     len = 79 - col;
  437.     if (weight)
  438.     lim = 68;
  439.     else
  440.     lim = 76;
  441.  
  442.     for (i = 0; i < 23; i++)
  443.     out_val[i][0] = '\0';
  444.  
  445.     k = 0;
  446.     for (i = r1; i <= r2; i++) {
  447.     if (test) {
  448.         if ((*test) (object_list[inventory[i].index].tval)) {
  449.         objdes(tmp_val, &inventory[i], TRUE);
  450.         tmp_val[lim] = 0;  /* Truncate if too long. */
  451.         (void)sprintf(out_val[i], "  %c) %s", 'a' + i, tmp_val);
  452.         l = strlen(out_val[i]);
  453.         if (weight)
  454.             l += 9;
  455.         if (l > len)
  456.             len = l;
  457.         k++;
  458.         }
  459.     } else {
  460.         objdes(tmp_val, &inventory[i], TRUE);
  461.         tmp_val[lim] = 0;       /* Truncate if too long. */
  462.         (void)sprintf(out_val[i], "  %c) %s", 'a' + i, tmp_val);
  463.         l = strlen(out_val[i]);
  464.         if (weight)
  465.         l += 9;
  466.         if (l > len)
  467.         len = l;
  468.         k++;
  469.     }
  470.     }
  471.  
  472.     col = 79 - len;
  473.     if (col < 0)
  474.     col = 0;
  475.  
  476.     j = 0;
  477.     for (i = r1; (i <= r2) && k; i++) {
  478.     if (out_val[i][0]) {
  479.         k--;
  480.     /* don't need first two spaces if in first column */
  481.         if (col == 0)
  482.         prt(&out_val[i][2], 1 + j, col);
  483.         else
  484.         prt(out_val[i], 1 + j, col);
  485.         if (weight) {
  486.         total_weight = inventory[i].weight * inventory[i].number;
  487.         (void)sprintf(tmp_val, "%3d.%d lb",
  488.                   (total_weight) / 10, (total_weight) % 10);
  489.         prt(tmp_val, 1 + j, 71);
  490.         }
  491.         j++;
  492.     }
  493.     }
  494.     erase_line(1+j,col);
  495.     return col;
  496. }
  497.  
  498.  
  499. /* Return a string describing how a given equipment item is carried. -CJS- */
  500. const char *
  501. describe_use(i)
  502. register int i;
  503. {
  504.     register const char *p;
  505.  
  506.     switch (i) {
  507.       case INVEN_WIELD:
  508.     p = "wielding";
  509.     break;
  510.       case INVEN_HEAD:
  511.     p = "wearing on your head";
  512.     break;
  513.       case INVEN_NECK:
  514.     p = "wearing around your neck";
  515.     break;
  516.       case INVEN_BODY:
  517.     p = "wearing on your body";
  518.     break;
  519.       case INVEN_ARM:
  520.     p = "wearing on your arm";
  521.     break;
  522.       case INVEN_HANDS:
  523.     p = "wearing on your hands";
  524.     break;
  525.       case INVEN_RIGHT:
  526.     p = "wearing on your right hand";
  527.     break;
  528.       case INVEN_LEFT:
  529.     p = "wearing on your left hand";
  530.     break;
  531.       case INVEN_FEET:
  532.     p = "wearing on your feet";
  533.     break;
  534.       case INVEN_OUTER:
  535.     p = "wearing about your body";
  536.     break;
  537.       case INVEN_LIGHT:
  538.     p = "using to light the way";
  539.     break;
  540.       case INVEN_AUX:
  541.     p = "holding ready by your side";
  542.     break;
  543.       default:
  544.     p = "carrying in your pack";
  545.     break;
  546.     }
  547.     return p;
  548. }
  549.  
  550.  
  551. /* Displays equipment items from r1 to end    -RAK-     */
  552. /* Keep display as far right as possible. -CJS- */
  553. int 
  554. show_equip(weight, col)
  555. int weight, col;
  556. {
  557.     register int         i, line;
  558.     int                  total_weight, l, len, lim;
  559.     register const char *prt1;
  560.     bigvtype             prt2;
  561.     vtype                out_val[INVEN_ARRAY_SIZE - INVEN_WIELD];
  562.     register inven_type *i_ptr;
  563.  
  564.     line = 0;
  565.     len = 79 - col;
  566.     if (weight)
  567.     lim = 52;
  568.     else
  569.     lim = 60;
  570.     for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++) {
  571.     i_ptr = &inventory[i];
  572.     if (i_ptr->tval != TV_NOTHING) {
  573.         switch (i) {
  574.           case INVEN_WIELD:
  575.         if (py.stats.use_stat[A_STR] * 15 < i_ptr->weight)
  576.             prt1 = "Just lifting";
  577.         else
  578.             prt1 = "Wielding";
  579.         break;
  580.           case INVEN_HEAD:
  581.         prt1 = "On head";
  582.         break;
  583.           case INVEN_NECK:
  584.         prt1 = "Around neck";
  585.         break;
  586.           case INVEN_BODY:
  587.         prt1 = "On body";
  588.         break;
  589.           case INVEN_ARM:
  590.         prt1 = "On arm";
  591.         break;
  592.           case INVEN_HANDS:
  593.         prt1 = "On hands";
  594.         break;
  595.           case INVEN_RIGHT:
  596.         prt1 = "On right hand";
  597.         break;
  598.           case INVEN_LEFT:
  599.         prt1 = "On left hand";
  600.         break;
  601.           case INVEN_FEET:
  602.         prt1 = "On feet";
  603.         break;
  604.           case INVEN_OUTER:
  605.         prt1 = "About body";
  606.         break;
  607.           case INVEN_LIGHT:
  608.         prt1 = "Light source";
  609.         break;
  610.           case INVEN_AUX:
  611.         prt1 = "Spare weapon";
  612.         break;
  613.           default:
  614.         prt1 = "Unknown value";
  615.         break;
  616.         }
  617.         objdes(prt2, &inventory[i], TRUE);
  618.         prt2[lim] = 0;       /* Truncate if necessary */
  619.         (void)sprintf(out_val[line], "  %c) %-14s: %s", line + 'a',
  620.               prt1, prt2);
  621.         l = strlen(out_val[line]);
  622.         if (weight)
  623.         l += 9;
  624.         if (l > len)
  625.         len = l;
  626.         line++;
  627.     }
  628.     }
  629.     col = 79 - len;
  630.     if (col < 0)
  631.     col = 0;
  632.  
  633.     line = 0;
  634.     for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++) {
  635.     i_ptr = &inventory[i];
  636.     if (i_ptr->tval != TV_NOTHING) {
  637.     /* don't need first two spaces when using whole screen */
  638.         if (col == 0)
  639.         prt(&out_val[line][2], line + 1, col);
  640.         else
  641.         prt(out_val[line], line + 1, col);
  642.         if (weight) {
  643.         total_weight = i_ptr->weight * i_ptr->number;
  644.         (void)sprintf(prt2, "%3d.%d lb",
  645.                   (total_weight) / 10, (total_weight) % 10);
  646.         prt(prt2, line + 1, 71);
  647.         }
  648.         line++;
  649.     }
  650.     }
  651.     erase_line(line + 1, col);
  652.     return col;
  653. }
  654.  
  655. /* Remove item from equipment list        -RAK-     */
  656. void 
  657. takeoff(item_val, posn)
  658. int item_val, posn;
  659. {
  660.     register const char *p;
  661.     bigvtype             out_val, prt2;
  662.     register inven_type *t_ptr;
  663.  
  664.     equip_ctr--;
  665.     t_ptr = &inventory[item_val];
  666.     inven_weight -= t_ptr->weight * t_ptr->number;
  667.     py.flags.status |= PY_STR_WGT;
  668.  
  669.     if (item_val == INVEN_WIELD || item_val == INVEN_AUX)
  670.     p = "Was wielding ";
  671.     else if (item_val == INVEN_LIGHT)
  672.     p = "Light source was ";
  673.     else
  674.     p = "Was wearing ";
  675.  
  676.     objdes(prt2, t_ptr, TRUE);
  677.     if (posn >= 0)
  678.     (void)sprintf(out_val, "%s%s. (%c)", p, prt2, 'a' + posn);
  679.     else if (posn == -1)
  680.     (void)sprintf(out_val, "%s%s.", p, prt2);
  681.     msg_print(out_val);
  682.     if (item_val != INVEN_AUX)       /* For secondary weapon  */
  683.     py_bonuses(t_ptr, -1);
  684.     invcopy(t_ptr, OBJ_NOTHING);
  685. }
  686.  
  687.  
  688. /* Used to verify if this really is the item we wish to wear or read. */
  689. int 
  690. verify(prompt, item)
  691. const char *prompt;
  692. int         item;
  693. {
  694.     bigvtype out_str, object;
  695.  
  696.     objdes(object, &inventory[item], TRUE);
  697.     (void)sprintf(out_str, "%s %s? ", prompt, object);
  698.     return get_check(out_str);
  699. }
  700.  
  701.  
  702. /*
  703.  * All inventory commands (wear, exchange, take off, drop, inventory and
  704.  * equipment) are handled in an alternative command input mode, which accepts
  705.  * any of the inventory commands. 
  706.  *
  707.  * It is intended that this function be called several times in succession, as
  708.  * some commands take up a turn, and the rest of moria must proceed in the
  709.  * interim. A global variable is provided, doing_inven, which is normally
  710.  * zero; however if on return from inven_command it is expected that
  711.  * inven_command should be called *again*, (being still in inventory command
  712.  * input mode), then doing_inven is set to the inventory command character
  713.  * which should be used in the next call to inven_command. 
  714.  *
  715.  * On return, the screen is restored, but not flushed. Provided no flush of the
  716.  * screen takes place before the next call to inven_command, the inventory
  717.  * command screen is silently redisplayed, and no actual output takes place
  718.  * at all. If the screen is flushed before a subsequent call, then the player
  719.  * is prompted to see if we should continue. This allows the player to see
  720.  * any changes that take place on the screen during inventory command input. 
  721.  *
  722.  * The global variable, screen_change, is cleared by inven_command, and set when
  723.  * the screen is flushed. This is the means by which inven_command tell if
  724.  * the screen has been flushed. 
  725.  *
  726.  * The display of inventory items is kept to the right of the screen to minimize
  727.  * the work done to restore the screen afterwards.        -CJS- 
  728.  */
  729.  
  730. /* Inventory command screen states. */
  731. #define BLANK_SCR    0
  732. #define EQUIP_SCR    1
  733. #define INVEN_SCR    2
  734. #define WEAR_SCR    3
  735. #define HELP_SCR    4
  736. #define WRONG_SCR    5
  737.  
  738. /* Keep track of the state of the inventory screen. */
  739. static int scr_state, scr_left, scr_base;
  740. static int wear_low, wear_high;
  741.  
  742. /* Draw the inventory screen. */
  743. static void 
  744. inven_screen(new_scr)
  745. int new_scr;
  746. {
  747.     register int line = 0;
  748.  
  749.     if (new_scr != scr_state) {
  750.     scr_state = new_scr;
  751.     switch (new_scr) {
  752.       case BLANK_SCR:
  753.         line = 0;
  754.         break;
  755.       case HELP_SCR:
  756.         if (scr_left > 52)
  757.         scr_left = 52;
  758.         prt("  e  : list used equipment", 1, scr_left);
  759.         prt("  i  : inventory of pack", 2, scr_left);
  760.         prt("  t  : take off item", 3, scr_left);
  761.         prt("  w  : wear or wield object", 4, scr_left);
  762.         prt("  x  : exchange weapons", 5, scr_left);
  763.         prt("  d  : drop object", 6, scr_left);
  764.         prt("  ESC: exit", 7, scr_left);
  765.         line = 7;
  766.         break;
  767.       case INVEN_SCR:
  768.         scr_left = show_inven(0, inven_ctr - 1, show_weight_flag, scr_left, 0);
  769.         line = inven_ctr;
  770.         break;
  771.       case WEAR_SCR:
  772.         scr_left = show_inven(wear_low, wear_high, show_weight_flag, scr_left, 0);
  773.         line = wear_high - wear_low + 1;
  774.         break;
  775.       case EQUIP_SCR:
  776.         scr_left = show_equip(show_equip_weight_flag, scr_left);
  777.         line = equip_ctr;
  778.         break;
  779.     }
  780.     if (line >= scr_base) {
  781.         scr_base = line + 1;
  782.         erase_line(scr_base, scr_left);
  783.     } else {
  784.         while (++line <= scr_base)
  785.         erase_line(line, scr_left);
  786.     }
  787.     }
  788. }
  789.  
  790. /* This does all the work. */
  791. void 
  792. inven_command(command)
  793. int command;
  794. {
  795.     register int         slot = 0, item;
  796.     int                  tmp, tmp2, selecting, from, to, light_chg = FALSE;
  797.     const char          *prompt, *swap, *disp, *string;
  798.     char                 which, query;
  799.     bigvtype             prt1, prt2;
  800.     register inven_type *i_ptr;
  801.     inven_type           tmp_obj;
  802.  
  803.     free_turn_flag = TRUE;
  804.     save_screen();
  805. /* Take up where we left off after a previous inventory command. -CJS- */
  806.     if (doing_inven) {
  807.     /* If the screen has been flushed, we need to redraw. If the command is a
  808.      * simple ' ' to recover the screen, just quit. Otherwise, check and see
  809.      * what the user wants. 
  810.      */
  811.     if (screen_change) {
  812.         if (command == ' ' || !get_check("Continuing with inventory command?")) {
  813.         doing_inven = FALSE;
  814.         return;
  815.         }
  816.         scr_left = 50;
  817.         scr_base = 0;
  818.     }
  819.     tmp = scr_state;
  820.     scr_state = WRONG_SCR;
  821.     inven_screen(tmp);
  822.     } else {
  823.     scr_left = 50;
  824.     scr_base = 0;
  825.     /* this forces exit of inven_command() if selecting is not set true */
  826.     scr_state = BLANK_SCR;
  827.     }
  828.     do {
  829.     if (isupper((int)command))
  830.         command = tolower((int)command);
  831.  
  832.     /* Simple command getting and screen selection. */
  833.     selecting = FALSE;
  834.     switch (command) {
  835.       case 'i':           /* Inventory        */
  836.         if (inven_ctr == 0)
  837.         msg_print("You are not carrying anything.");
  838.         else
  839.         inven_screen(INVEN_SCR);
  840.         break;
  841.       case 'e':           /* Equipment       */
  842.         if (equip_ctr == 0)
  843.         msg_print("You are not using any equipment.");
  844.         else
  845.         inven_screen(EQUIP_SCR);
  846.         break;
  847.       case 't':           /* Take off       */
  848.         if (equip_ctr == 0)
  849.         msg_print("You are not using any equipment.");
  850.     /* don't print message restarting inven command after taking off
  851.      * something, it is confusing 
  852.      */
  853.         else if (inven_ctr >= INVEN_WIELD && !doing_inven)
  854.         msg_print("You will have to drop something first.");
  855.         else {
  856.         if (scr_state != BLANK_SCR)
  857.             inven_screen(EQUIP_SCR);
  858.         selecting = TRUE;
  859.         }
  860.         break;
  861.       case 'd':           /* Drop */
  862.         if (inven_ctr == 0 && equip_ctr == 0)
  863.         msg_print("But you're not carrying anything.");
  864.         else if (cave[char_row][char_col].tptr != 0)
  865.         msg_print("There's no room to drop anything here.");
  866.         else {
  867.         selecting = TRUE;
  868.         if ((scr_state == EQUIP_SCR && equip_ctr > 0) || inven_ctr == 0) {
  869.             if (scr_state != BLANK_SCR)
  870.             inven_screen(EQUIP_SCR);
  871.             command = 'r'; /* Remove - or take off and drop. */
  872.         } else if (scr_state != BLANK_SCR)
  873.             inven_screen(INVEN_SCR);
  874.         }
  875.         break;
  876.       case 'w':           /* Wear/wield       */
  877.         for (wear_low = 0;
  878.          wear_low < inven_ctr && inventory[wear_low].tval > TV_MAX_WEAR;
  879.          wear_low++);
  880.         for (wear_high = wear_low;
  881.          wear_high < inven_ctr && inventory[wear_high].tval >= TV_MIN_WEAR;
  882.          wear_high++);
  883.         wear_high--;
  884.         if (wear_low > wear_high)
  885.         msg_print("You have nothing to wear or wield.");
  886.         else {
  887.         if (scr_state != BLANK_SCR && scr_state != INVEN_SCR)
  888.             inven_screen(WEAR_SCR);
  889.         selecting = TRUE;
  890.         }
  891.         break;
  892.       case 'x':
  893.         if (inventory[INVEN_WIELD].tval == TV_NOTHING &&
  894.         inventory[INVEN_AUX].tval == TV_NOTHING)
  895.         msg_print("But you are wielding no weapons.");
  896.         else if (TR_CURSED & inventory[INVEN_WIELD].flags) {
  897.         objdes(prt1, &inventory[INVEN_WIELD], FALSE);
  898.         (void)sprintf(prt2,
  899.              "The %s you are wielding appears to be cursed.", prt1);
  900.         msg_print(prt2);
  901.         } else {
  902.         free_turn_flag = FALSE;
  903.         tmp_obj = inventory[INVEN_AUX];
  904.         inventory[INVEN_AUX] = inventory[INVEN_WIELD];
  905.         inventory[INVEN_WIELD] = tmp_obj;
  906.         if (scr_state == EQUIP_SCR)
  907.             scr_left = show_equip(show_weight_flag, scr_left);
  908.         py_bonuses(&inventory[INVEN_AUX], -1);    /* Subtract bonuses */
  909.         py_bonuses(&inventory[INVEN_WIELD], 1);    /* Add bonuses    */
  910.  
  911.         if (inventory[INVEN_WIELD].tval != TV_NOTHING) {
  912.             (void)strcpy(prt1, "Primary weapon   : ");
  913.             objdes(prt2, &inventory[INVEN_WIELD], TRUE);
  914.             msg_print(strcat(prt1, prt2));
  915.         } else
  916.             msg_print("No primary weapon.");
  917.  
  918.         /* this is a new weapon, so clear the heavy flag */
  919. /* no, don't; the check_strength will clear it if it needs to be cleared
  920.         weapon_heavy = FALSE; */
  921.         check_strength();
  922.         }
  923.         break;
  924.       case ' ':           /* Dummy command to return again to main
  925.                     * prompt. */
  926.         break;
  927.       case '?':
  928.         inven_screen(HELP_SCR);
  929.         break;
  930.       default:
  931.     /* Nonsense command                       */
  932.         bell();
  933.         break;
  934.     }
  935.  
  936.     /* Clear the doing_inven flag here, instead of at beginning, so that can
  937.      * use it to control when messages above appear. 
  938.      */
  939.     doing_inven = 0;
  940.  
  941.     /* Keep looking for objects to drop/wear/take off/throw off */
  942.     which = 'z';
  943.     while (selecting && free_turn_flag) {
  944.         swap = "";
  945.         if (command == 'w') {
  946.         from = wear_low;
  947.         to = wear_high;
  948.         prompt = "Wear/Wield";
  949.         } else {
  950.         from = 0;
  951.         if (command == 'd') {
  952.             to = inven_ctr - 1;
  953.             prompt = "Drop";
  954.             if (equip_ctr > 0)
  955.             swap = ", / for Equip";
  956.         } else {
  957.             to = equip_ctr - 1;
  958.             if (command == 't')
  959.             prompt = "Take off";
  960.             else {       /* command == 'r' */
  961.             prompt = "Throw off";
  962.             if (inven_ctr > 0)
  963.                 swap = ", / for Inven";
  964.             }
  965.         }
  966.         }
  967.         if (from > to)
  968.         selecting = FALSE;
  969.         else {
  970.         if (scr_state == BLANK_SCR)
  971.             disp = ", * to list";
  972.         else
  973.             disp = "";
  974.         (void)sprintf(prt1,
  975.            "(%c-%c%s%s, space to break, ESC to exit) %s which one?",
  976.                   from + 'a', to + 'a', disp, swap, prompt);
  977.  
  978.         /* Abort everything. */
  979.         if (!get_com(prt1, &which)) {
  980.             selecting = FALSE;
  981.             which = ESCAPE;
  982.         }
  983.         /* Draw the screen and maybe exit to main prompt. */
  984.         else if (which == ' ' || which == '*') {
  985.             if (command == 't' || command == 'r')
  986.             inven_screen(EQUIP_SCR);
  987.             else if (command == 'w' && scr_state != INVEN_SCR)
  988.             inven_screen(WEAR_SCR);
  989.             else
  990.             inven_screen(INVEN_SCR);
  991.             if (which == ' ')
  992.             selecting = FALSE;
  993.         }
  994.         /* Swap screens (for drop) */
  995.         else if (which == '/' && swap[0]) {
  996.             if (command == 'd')
  997.             command = 'r';
  998.             else
  999.             command = 'd';
  1000.             if (scr_state == EQUIP_SCR)
  1001.             inven_screen(INVEN_SCR);
  1002.             else if (scr_state == INVEN_SCR)
  1003.             inven_screen(EQUIP_SCR);
  1004.         } else if (((which < from + 'a') || (which > to + 'a'))
  1005.                && ((which < from + 'A') || (which > to + 'A')))
  1006.             bell();
  1007.         else {           /* Found an item! */
  1008.             if (isupper((int)which))
  1009.             item = which - 'A';
  1010.             else
  1011.             item = which - 'a';
  1012.             if (command == 'r' || command == 't') {
  1013.             /* Get its place in the equipment list. */
  1014.             tmp = item;
  1015.             item = 21;
  1016.             do {
  1017.                 item++;
  1018.                 if (inventory[item].tval != TV_NOTHING)
  1019.                 tmp--;
  1020.             }
  1021.             while (tmp >= 0);
  1022.             if (isupper((int)which) && !verify(prompt, item))
  1023.                 item = (-1);
  1024.             else if (TR_CURSED & inventory[item].flags) {
  1025.                 msg_print("Hmmm, it seems to be cursed.");
  1026.                 item = (-1);
  1027.             } else if (command == 't' &&
  1028.                    !inven_check_num(&inventory[item])) {
  1029.                 if (cave[char_row][char_col].tptr != 0) {
  1030.                 msg_print("You can't carry it.");
  1031.                 item = (-1);
  1032.                 } else if (get_check("You can't carry it.  Drop it?"))
  1033.                 command = 'r';
  1034.                 else
  1035.                 item = (-1);
  1036.             }
  1037.             if (item >= 0)
  1038.                 if (item == INVEN_LIGHT)
  1039.                 light_chg = TRUE;
  1040.             if (command == 'r') {
  1041.                 inven_drop(item, TRUE);
  1042.  
  1043.                 /* As a safety measure, set the player's inven weight to 0,
  1044.                  * when the last object is dropped */
  1045.                 if (inven_ctr == 0 && equip_ctr == 0)
  1046.                 inven_weight = 0;
  1047.             } else if (item >= 0) {
  1048.                 slot = inven_carry(&inventory[item]);
  1049.                 takeoff(item, slot);
  1050.             }
  1051.             check_strength();
  1052.             free_turn_flag = FALSE;
  1053.             if (command == 'r')
  1054.                 selecting = FALSE;
  1055.             } else if (command == 'w') {
  1056.  
  1057.     /* Wearing. Go to a bit of trouble over replacing existing equipment. */
  1058.             if (isupper((int)which) && !verify(prompt, item))
  1059.                 item = (-1);
  1060.             else
  1061.                 switch (inventory[item].tval) { /* Slot for equipment */
  1062.                   case TV_SLING_AMMO:
  1063.                   case TV_BOLT:
  1064.                   case TV_ARROW:
  1065.                   case TV_BOW:
  1066.                   case TV_HAFTED:
  1067.                   case TV_POLEARM:
  1068.                   case TV_SWORD:
  1069.                   case TV_DIGGING:
  1070.                 slot = INVEN_WIELD;
  1071.                 break;
  1072.                   case TV_LIGHT:
  1073.                 slot = INVEN_LIGHT;
  1074.                 break;
  1075.                   case TV_BOOTS:
  1076.                 slot = INVEN_FEET;
  1077.                 break;
  1078.                   case TV_GLOVES:
  1079.                 slot = INVEN_HANDS;
  1080.                 break;
  1081.                   case TV_CLOAK:
  1082.                 slot = INVEN_OUTER;
  1083.                 break;
  1084.                   case TV_HELM:
  1085.                 slot = INVEN_HEAD;
  1086.                 break;
  1087.                   case TV_SHIELD:
  1088.                 slot = INVEN_ARM;
  1089.                 break;
  1090.                   case TV_HARD_ARMOR:
  1091.                   case TV_SOFT_ARMOR:
  1092.                 slot = INVEN_BODY;
  1093.                 break;
  1094.                   case TV_AMULET:
  1095.                 slot = INVEN_NECK;
  1096.                 break;
  1097.                   case TV_RING:
  1098.                 if (inventory[INVEN_RIGHT].tval == TV_NOTHING)
  1099.                     slot = INVEN_RIGHT;
  1100.                 else if (inventory[INVEN_LEFT].tval == TV_NOTHING)
  1101.                     slot = INVEN_LEFT;
  1102.                 else {
  1103.                     slot = 0;
  1104.                 /*
  1105.                  * Rings. Give some choice over where they
  1106.                  * go. 
  1107.                  */
  1108.                     do {
  1109.                     if (!get_com(
  1110.                  "Put ring on which hand (l/r/L/R)?", &query)) {
  1111.                         item = (-1);
  1112.                         slot = (-1);
  1113.                     } else if (query == 'l')
  1114.                         slot = INVEN_LEFT;
  1115.                     else if (query == 'r')
  1116.                         slot = INVEN_RIGHT;
  1117.                     else {
  1118.                         if (query == 'L')
  1119.                         slot = INVEN_LEFT;
  1120.                         else if (query == 'R')
  1121.                         slot = INVEN_RIGHT;
  1122.                         else
  1123.                         bell();
  1124.                         if (slot && !verify("Replace", slot))
  1125.                         slot = 0;
  1126.                     }
  1127.                     }
  1128.                     while (slot == 0);
  1129.                 }
  1130.                 break;
  1131.                   default:
  1132.         msg_print("IMPOSSIBLE: I don't see how you can use that.");
  1133.                 item = (-1);
  1134.                 break;
  1135.                 }
  1136.             if (item >= 0 && inventory[slot].tval != TV_NOTHING) {
  1137.                 if (TR_CURSED & inventory[slot].flags) {
  1138.                 objdes(prt1, &inventory[slot], FALSE);
  1139.                 (void)sprintf(prt2, "The %s you are ", prt1);
  1140.                 if (slot == INVEN_WIELD)    /* changed from
  1141.                                  * INVEN_HEAD -CFT */
  1142.                     (void)strcat(prt2, "wielding ");
  1143.                 else
  1144.                     (void)strcat(prt2, "wearing ");
  1145.                 msg_print(strcat(prt2, "appears to be cursed."));
  1146.                 item = (-1);
  1147.                 } else if (inventory[item].subval == ITEM_GROUP_MIN &&
  1148.                        inventory[item].number > 1 &&
  1149.                        !inven_check_num(&inventory[slot])) {
  1150.  /* this can happen if try to wield a torch, and have more than one in your inventory */
  1151.                 msg_print("You will have to drop something first.");
  1152.                 item = (-1);
  1153.                 }
  1154.             }
  1155.             if (item >= 0) {
  1156.             /* OK. Wear it. */
  1157.                 free_turn_flag = FALSE;
  1158.  
  1159.                 if (slot == INVEN_LIGHT)
  1160.                 light_chg = TRUE;
  1161.  
  1162.             /* first remove new item from inventory */
  1163.                 tmp_obj = inventory[item];
  1164.                 i_ptr = &tmp_obj;
  1165.  
  1166.                 wear_high--;
  1167.             /* Fix for torches       */
  1168.                 if (i_ptr->number > 1
  1169.                 && i_ptr->subval <= ITEM_SINGLE_STACK_MAX) {
  1170.                 i_ptr->number = 1;
  1171.                 wear_high++;
  1172.                 }
  1173.                 inven_weight += i_ptr->weight * i_ptr->number;
  1174.                 inven_destroy(item);    /* Subtracts weight */
  1175.  
  1176. /* second, add old item to inv and remove from equipment list, if necessary */
  1177.                 i_ptr = &inventory[slot];
  1178.                 if (i_ptr->tval != TV_NOTHING) {
  1179.                 tmp2 = inven_ctr;
  1180.                 tmp = inven_carry(i_ptr);
  1181. /* if item removed did not stack with anything in inventory, then increment wear_high */
  1182.                 if (inven_ctr != tmp2)
  1183.                     wear_high++;
  1184.                 takeoff(slot, tmp);
  1185.                 }
  1186.             /* third, wear new item */
  1187.                 *i_ptr = tmp_obj;
  1188.                 equip_ctr++;
  1189.                 py_bonuses(i_ptr, 1);
  1190.                 if (slot == INVEN_WIELD)
  1191.                 string = "You are wielding";
  1192.                 else if (slot == INVEN_LIGHT)
  1193.                 string = "Your light source is";
  1194.                 else
  1195.                 string = "You are wearing";
  1196.                 objdes(prt2, i_ptr, TRUE);
  1197.             /* Get the right equipment letter. */
  1198.                 tmp = INVEN_WIELD;
  1199.                 item = 0;
  1200.                 while (tmp != slot)
  1201.                 if (inventory[tmp++].tval != TV_NOTHING)
  1202.                     item++;
  1203.  
  1204.                 (void)sprintf(prt1, "%s %s. (%c)", string, prt2,
  1205.                       'a' + item);
  1206.                 msg_print(prt1);
  1207.             /* check_str will clear the heavy flag if necessary */
  1208.                 check_strength();
  1209.                 if (i_ptr->flags & TR_CURSED) {
  1210.                 msg_print("Oops! It feels deathly cold!");
  1211.                 add_inscribe(i_ptr, ID_DAMD);
  1212.                 /* To force a cost of 0, even if unidentified. */
  1213.                 /* i_ptr->cost = (-1); Not... */
  1214.                 }
  1215.             }
  1216.             } else {       /* command == 'd' */
  1217.             if (inventory[item].number > 1) {
  1218.                 objdes(prt1, &inventory[item], TRUE);
  1219.                 (void)sprintf(prt2, "Drop all %s?  [y/n]", prt1);
  1220.                 prt(prt2, 0, 0);
  1221.                 query = inkey();
  1222.                 if (query != 'y' && query != 'n') {
  1223.                 if (query != ESCAPE)
  1224.                     bell();
  1225.                 erase_line(MSG_LINE, 0);
  1226.                 item = (-1);
  1227.                 }
  1228.             } else if (isupper((int)which) && !verify(prompt, item))
  1229.                 item = (-1);
  1230.             else
  1231.                 query = 'y';
  1232.             if (item >= 0) {
  1233.                 free_turn_flag = FALSE;    /* Player turn   */
  1234.                 inven_drop(item, query == 'y');
  1235.                 check_strength();
  1236.             }
  1237.             selecting = FALSE;
  1238.             /* As a safety measure, set the player's inven weight to 0,
  1239.              * when the last object is dropped. */
  1240.             if (inven_ctr == 0 && equip_ctr == 0)
  1241.                 inven_weight = 0;
  1242.             }
  1243.             if (free_turn_flag == FALSE && scr_state == BLANK_SCR)
  1244.             selecting = FALSE;
  1245.         }
  1246.         }
  1247.     }
  1248.     if (which == ESCAPE || scr_state == BLANK_SCR)
  1249.         command = ESCAPE;
  1250.     else if (!free_turn_flag) {
  1251.     /* Save state for recovery if they want to call us again next turn. */
  1252.         if (selecting)
  1253.         doing_inven = command;
  1254.         else
  1255.         doing_inven = ' '; /* A dummy command to recover screen. */
  1256.     /* flush last message before clearing screen_change and exiting */
  1257.         msg_print(NULL);
  1258.         screen_change = FALSE; /* This lets us know if the world changes */
  1259.         command = ESCAPE;
  1260.     } else {
  1261.     /* Put an appropriate header. */
  1262.         if (scr_state == INVEN_SCR) {
  1263.         if (!show_weight_flag || inven_ctr == 0)
  1264.             (void)sprintf(prt1,
  1265.               "You are carrying %d.%d pounds. In your pack there is %s",
  1266.                   inven_weight / 10, inven_weight % 10,
  1267.                   (inven_ctr == 0 ? "nothing." : "-"));
  1268.         else
  1269.             (void)sprintf(prt1,
  1270.           "You are carrying %d.%d pounds. Your capacity is %d.%d pounds. %s",
  1271.                   inven_weight / 10, inven_weight % 10,
  1272.                   weight_limit() / 10, weight_limit() % 10,
  1273.                   "In your pack is -");
  1274.         prt(prt1, 0, 0);
  1275.         } else if (scr_state == WEAR_SCR) {
  1276.         if (wear_high < wear_low)
  1277.             prt("You have nothing you could wield.", 0, 0);
  1278.         else
  1279.             prt("You could wield -", 0, 0);
  1280.         } else if (scr_state == EQUIP_SCR) {
  1281.         if (equip_ctr == 0)
  1282.             prt("You are not using anything.", 0, 0);
  1283.         else
  1284.             prt("You are using -", 0, 0);
  1285.         } else
  1286.         prt("Allowed commands:", 0, 0);
  1287.         erase_line(scr_base, scr_left);
  1288.         put_buffer("e/i/t/w/x/d/?/ESC:", scr_base, 60);
  1289.         command = inkey();
  1290.         erase_line(scr_base, scr_left);
  1291.     }
  1292.     }
  1293.     while (command != ESCAPE);
  1294.     if (scr_state != BLANK_SCR)
  1295.     restore_screen();
  1296.  
  1297. /* Update screen for changed light radius. -DGK */
  1298. /* Fix redisplay of lighting when in stores. -DGK */
  1299.     if (light_chg && !in_store_flag) {
  1300.     register int        i, j;
  1301.     int                 min_i, max_i, min_j, max_j;
  1302.  
  1303. /* replace a check for in_bounds2 every loop with 4 quick computations -CWS */
  1304.     min_i = MY_MAX(0, (char_row - light_rad));
  1305.     max_i = MY_MIN(cur_height, (char_row + light_rad));
  1306.     min_j = MY_MAX(0, (char_col - light_rad));
  1307.     max_j = MY_MIN(cur_width, (char_col + light_rad));
  1308.  
  1309.     for (i = min_i; i <= max_i; i++)
  1310.         for (j = min_j; j <= max_j; j++)
  1311.         cave[i][j].tl = FALSE;
  1312.  
  1313. #ifdef TC_COLOR
  1314.     textcolor(LIGHTGRAY);
  1315. #endif
  1316.     tmp2 = light_rad;
  1317.     print('@', char_row, char_col);
  1318.     if (inventory[INVEN_LIGHT].tval == TV_LIGHT)
  1319.         tmp = inventory[INVEN_LIGHT].subval;
  1320.     else
  1321.         tmp = 195;
  1322.     light_rad = 1 + (tmp < 190) + (tmp == 4 || tmp == 6);
  1323.     if (tmp2 < light_rad)
  1324.         tmp2 = light_rad;
  1325.  
  1326.     if (!py.flags.blind) {
  1327.         min_i = MY_MAX(0, (char_row - light_rad));
  1328.         max_i = MY_MIN(cur_height, (char_row + light_rad));
  1329.         min_j = MY_MAX(0, (char_col - light_rad));
  1330.         max_j = MY_MIN(cur_width, (char_col + light_rad));
  1331.  
  1332.         for (i = min_i; i <= max_i; i++)
  1333.         for (j = min_j; j <= max_j; j++)
  1334.             if (los(char_row, char_col, i, j) &&
  1335.             distance(char_row, char_col, i, j) <= light_rad)
  1336.             cave[i][j].tl = TRUE;
  1337.     }
  1338.  
  1339.     min_i = MY_MAX(0, (char_row - tmp2));
  1340.     max_i = MY_MIN(cur_height, (char_row + tmp2));
  1341.     min_j = MY_MAX(0, (char_col - tmp2));
  1342.     max_j = MY_MIN(cur_width, (char_col + tmp2));
  1343.     for (i = min_i; i <= max_i; i++)
  1344.         for (j = min_j; j <= max_j; j++)
  1345.         lite_spot(i, j);
  1346.     }
  1347.     calc_bonuses();
  1348.  
  1349.     /* If we ain't in a store, do the equippy chars -DGK*/
  1350.     if (!in_store_flag) 
  1351.     prt_equippy_chars();
  1352. }
  1353.  
  1354.  
  1355. /* Get the ID of an item and return the CTR value of it    -RAK-     */
  1356. int 
  1357. get_item(com_val, pmt, i, j, test)
  1358. int        *com_val;
  1359. const char *pmt;
  1360. int         i, j;
  1361. int       (*test) ();
  1362.  
  1363. {
  1364.     vtype        out_val;
  1365.     char         which;
  1366.     register int test_flag, item;
  1367.     int          full, i_scr, redraw;
  1368.  
  1369.     int on_floor, ih;
  1370.     cave_type *c_ptr;
  1371.  
  1372.     /* check we're a) identifying and b) on the floor is an object
  1373.      * and c) it is a object wich could be picked up
  1374.      */
  1375.  
  1376.     c_ptr = &cave[char_row][char_col];
  1377.     ih = t_list[c_ptr->tptr].tval;
  1378.     on_floor = ( (strcmp("Item you wish identified?",pmt) == 0) &&
  1379.          !( (c_ptr->tptr == 0) || ih == TV_NOTHING
  1380.             || ih > TV_MAX_PICK_UP) );
  1381.  
  1382.     item = FALSE;
  1383.     redraw = FALSE;
  1384.     *com_val = 0;
  1385.     i_scr = 1;
  1386.     if (j > INVEN_WIELD) {
  1387.     full = TRUE;
  1388.     if (inven_ctr == 0) {
  1389.         i_scr = 0;
  1390.         j = equip_ctr - 1;
  1391.     } else
  1392.         j = inven_ctr - 1;
  1393.     } else
  1394.     full = FALSE;
  1395.  
  1396.     if (inven_ctr > 0 || (full && equip_ctr > 0)) {
  1397.     do {
  1398.         if (redraw) {
  1399.         if (i_scr > 0)
  1400.             (void)show_inven(i, j, FALSE, 80, test);
  1401.         else
  1402.             (void)show_equip(FALSE, 80);
  1403.         }
  1404.         if (full)
  1405.         (void)sprintf(out_val,
  1406.                   "(%s: %c-%c,%s%s / for %s, or ESC) %s",
  1407.                  (i_scr > 0 ? "Inven" : "Equip"), i + 'a', j + 'a',
  1408.                   (on_floor ? " - floor," : ""),
  1409.                   (redraw ? "" : " * to see,"),
  1410.                   (i_scr > 0 ? "Equip" : "Inven"), pmt);
  1411.         else
  1412.         (void)sprintf(out_val,
  1413.             "(Items %c-%c,%s ESC to exit) %s", i + 'a', j + 'a',
  1414.                   (redraw ? "" : " * for inventory list,"), pmt);
  1415.         test_flag = FALSE;
  1416.         prt(out_val, 0, 0);
  1417.         do {
  1418.         which = inkey();
  1419.         switch (which) {
  1420.           case ESCAPE:
  1421.             test_flag = TRUE;
  1422.             free_turn_flag = TRUE;
  1423.             i_scr = (-1);
  1424.             break;
  1425.           case '/':
  1426.             if (full) {
  1427.             if (i_scr > 0) {
  1428.                 if (equip_ctr == 0) {
  1429.                 prt("But you're not using anything -more-", 0, 0);
  1430.                 (void)inkey();
  1431.                 } else {
  1432.                 i_scr = 0;
  1433.                 test_flag = TRUE;
  1434.                 if (redraw) {
  1435.                     j = equip_ctr;
  1436.                     while (j < inven_ctr) {
  1437.                     j++;
  1438.                     erase_line(j, 0);
  1439.                     }
  1440.                 }
  1441.                 j = equip_ctr - 1;
  1442.                 }
  1443.                 prt(out_val, 0, 0);
  1444.             } else {
  1445.                 if (inven_ctr == 0) {
  1446.                 prt("But you're not carrying anything -more-", 0, 0);
  1447.                 (void)inkey();
  1448.                 } else {
  1449.                 i_scr = 1;
  1450.                 test_flag = TRUE;
  1451.                 if (redraw) {
  1452.                     j = inven_ctr;
  1453.                     while (j < equip_ctr) {
  1454.                     j++;
  1455.                     erase_line(j, 0);
  1456.                     }
  1457.                 }
  1458.                 j = inven_ctr - 1;
  1459.                 }
  1460.             }
  1461.  
  1462.             }
  1463.             break;
  1464.           case '*':
  1465.             if (!redraw) {
  1466.             test_flag = TRUE;
  1467.             save_screen();
  1468.             redraw = TRUE;
  1469.             }
  1470.             break;
  1471.         case '-':
  1472.         /* not identified from INVEN or EQU but not aborted */
  1473.             if (on_floor) {
  1474.             item = FUZZY;
  1475.             test_flag = TRUE;
  1476.             i_scr = -1;
  1477.             break;
  1478.             }
  1479.           default:
  1480.             if (isupper((int)which))
  1481.             *com_val = which - 'A';
  1482.             else
  1483.             *com_val = which - 'a';
  1484.             if ((*com_val >= i) && (*com_val <= j)) {
  1485.             if (i_scr == 0) {
  1486.                 i = 21;
  1487.                 j = *com_val;
  1488.                 do {
  1489.                 while (inventory[++i].tval == TV_NOTHING);
  1490.                 j--;
  1491.                 }
  1492.                 while (j >= 0);
  1493.                 *com_val = i;
  1494.             }
  1495.             if (isupper((int)which) && !verify("Try", *com_val)) {
  1496.                 test_flag = TRUE;
  1497.                 free_turn_flag = TRUE;
  1498.                 i_scr = (-1);
  1499.                 break;
  1500.             }
  1501.             test_flag = TRUE;
  1502.             item = TRUE;
  1503.             i_scr = (-1);
  1504.             } else
  1505.             bell();
  1506.             break;
  1507.         }
  1508.         }
  1509.         while (!test_flag);
  1510.     }
  1511.     while (i_scr >= 0);
  1512.     if (redraw)
  1513.         restore_screen();
  1514.     erase_line(MSG_LINE, 0);
  1515.     } else
  1516.     prt("You are not carrying anything.", 0, 0);
  1517.     return (item);
  1518. }
  1519.  
  1520. /* I may have written the town level code, but I'm not exactly     */
  1521. /* proud of it.     Adding the stores required some real slucky     */
  1522. /* hooks which I have not had time to re-think.         -RAK-     */
  1523.  
  1524. /* Returns true if player has no light            -RAK-     */
  1525. int 
  1526. no_light()
  1527. {
  1528.     register cave_type *c_ptr;
  1529.  
  1530.     c_ptr = &cave[char_row][char_col];
  1531.     if (!c_ptr->tl && !c_ptr->pl)
  1532.     return TRUE;
  1533.     return FALSE;
  1534. }
  1535.  
  1536.  
  1537. /* map rogue_like direction commands into numbers */
  1538. static char 
  1539. map_roguedir(my_comval)
  1540. register int my_comval;
  1541. {
  1542.     char comval = (char)my_comval;
  1543.  
  1544.     switch (comval) {
  1545.       case 'h':
  1546.     comval = '4';
  1547.     break;
  1548.       case 'y':
  1549.     comval = '7';
  1550.     break;
  1551.       case 'k':
  1552.     comval = '8';
  1553.     break;
  1554.       case 'u':
  1555.     comval = '9';
  1556.     break;
  1557.       case 'l':
  1558.     comval = '6';
  1559.     break;
  1560.       case 'n':
  1561.     comval = '3';
  1562.     break;
  1563.       case 'j':
  1564.     comval = '2';
  1565.     break;
  1566.       case 'b':
  1567.     comval = '1';
  1568.     break;
  1569.       case '.':
  1570.     comval = '5';
  1571.     break;
  1572.     }
  1573.     return (comval);
  1574. }
  1575.  
  1576.  
  1577. /* Prompts for a direction                -RAK-     */
  1578. /* Direction memory added, for repeated commands.  -CJS */
  1579. int 
  1580. get_dir(prompt, dir)
  1581. const char *prompt;
  1582. int        *dir;
  1583. {
  1584.     char        command;
  1585.     int         save;
  1586.     static char prev_dir;  /* Direction memory. -CJS- */
  1587.  
  1588.     if (default_dir) {           /* used in counted commands. -CJS- */
  1589.     *dir = prev_dir;
  1590.     return TRUE;
  1591.     }
  1592. #ifdef TARGET
  1593. /* This targetting code stolen from Morgul -CFT */
  1594. /* Aggle.  Gotta be target mode and either (valid monster and line of sight*/
  1595. /* to monster) or (not valid monster and line of sight to position).  CDW */
  1596. /* Also, for monster targetting, monster must be lit!  Otherwise player can
  1597.    "lock phasers" on an invis monster while a potion of see inv lasts,
  1598.    and then continue to hit it when the see inv goes away.  Also,
  1599.    targetting mode shouldn't help the player shoot a monster in a
  1600.    dark room.  If he can't see it, he shouldn't be able to aim... -CFT */
  1601.     if ((target_mode)&&
  1602.     (((target_mon<MAX_MALLOC)&& m_list[target_mon].ml &&
  1603.       (los(char_row,char_col,m_list[target_mon].fy,m_list[target_mon].fx))||
  1604.       ((target_mon>=MAX_MALLOC) &&
  1605.        (los(char_row,char_col,target_row,target_col)))))) {
  1606.       /* It don't get no better than this */
  1607.     *dir=0;
  1608.     return TRUE;
  1609.     }
  1610.     else {
  1611. #endif
  1612.     if (prompt == NULL)
  1613.     prompt = "Which direction?";
  1614.     for (;;) {
  1615.     save = command_count;       /* Don't end a counted command. -CJS- */
  1616. #ifdef MAC
  1617.     if (!get_comdir(prompt, &command))
  1618. #else
  1619.     if (!get_com(prompt, &command))
  1620. #endif
  1621.     {
  1622.         free_turn_flag = TRUE;
  1623.         return FALSE;
  1624.     }
  1625.     command_count = save;
  1626.     if (rogue_like_commands)
  1627.         command = map_roguedir(command);
  1628.     if (command >= '1' && command <= '9' && command != '5') {
  1629.         prev_dir = command - '0';
  1630.         *dir = prev_dir;
  1631.         return TRUE;
  1632.     }
  1633.     bell();
  1634.     }
  1635. #ifdef TARGET
  1636.     }
  1637. #endif
  1638. }
  1639.  
  1640.  
  1641.  
  1642. /*
  1643.  * Similar to get_dir, except that no memory exists, and it is        -CJS-
  1644.  * allowed to enter the null direction. 
  1645.  */
  1646. int 
  1647. get_alldir(prompt, dir)
  1648. const char *prompt;
  1649. int *dir;
  1650. {
  1651.     char command;
  1652.  
  1653.     for (;;) {
  1654. #ifdef MAC
  1655.     if (!get_comdir(prompt, &command))
  1656. #else
  1657.     if (!get_com(prompt, &command))
  1658. #endif
  1659.     {
  1660.         free_turn_flag = TRUE;
  1661.         return FALSE;
  1662.     }
  1663.     if (rogue_like_commands)
  1664.         command = map_roguedir(command);
  1665.     if (command >= '1' && command <= '9') {
  1666.         *dir = command - '0';
  1667.         return TRUE;
  1668.     }
  1669.     bell();
  1670.     }
  1671. }
  1672.  
  1673.  
  1674. /* Moves creature record from one space to another    -RAK-     */
  1675. void 
  1676. move_rec(y1, x1, y2, x2)
  1677. register int y1, x1, y2, x2;
  1678. {
  1679.     int tmp;
  1680.  
  1681. /* this always works correctly, even if y1==y2 and x1==x2 */
  1682.     tmp = cave[y1][x1].cptr;
  1683.     cave[y1][x1].cptr = 0;
  1684.     cave[y2][x2].cptr = tmp;
  1685. }
  1686.  
  1687. static void
  1688. flood_light(y,x)
  1689. int y,x;
  1690. {
  1691.     register cave_type *c_ptr;
  1692.     register int temp;
  1693.     c_ptr = &cave[y][x];
  1694.     if (c_ptr->lr) {
  1695.     temp=c_ptr->tl;
  1696.     c_ptr->tl = TRUE;
  1697.     if (c_ptr->fval<MIN_CLOSED_SPACE && temp==FALSE) {
  1698.         flood_light(y+1,x);
  1699.         flood_light(y-1,x);
  1700.         flood_light(y,x+1);
  1701.         flood_light(y,x-1);
  1702.         flood_light(y+1,x+1);
  1703.         flood_light(y-1,x-1);
  1704.         flood_light(y-1,x+1);
  1705.         flood_light(y+1,x-1);
  1706.     }
  1707.     }
  1708. }
  1709.  
  1710. static void flood_permanent(y,x)
  1711. int y,x;
  1712. {
  1713.     register cave_type *c_ptr;
  1714.     c_ptr = &cave[y][x];
  1715.     if (c_ptr->tl) {
  1716.     c_ptr->tl = FALSE;
  1717.     c_ptr->pl = TRUE;
  1718.     if (c_ptr->fval==NT_DARK_FLOOR)
  1719.         c_ptr->fval=NT_LIGHT_FLOOR;
  1720.     else if (c_ptr->fval==DARK_FLOOR)
  1721.         c_ptr->fval=LIGHT_FLOOR;
  1722. #ifdef MSDOS
  1723.     lite_spot(y,x); /* this does all that; plus color-safe -CFT */
  1724. #else
  1725.     if ((y-panel_row_prt)<23 && (y-panel_row_prt)>0 &&
  1726.         (x-panel_col_prt)>12 && (x-panel_col_prt)<80)
  1727.         print(loc_symbol(y, x), y, x);
  1728. #endif
  1729.     if (c_ptr->fval<MIN_CLOSED_SPACE) {
  1730.         flood_permanent(y+1,x);
  1731.       flood_permanent(y-1,x);
  1732.         flood_permanent(y,x+1);
  1733.         flood_permanent(y,x-1);
  1734.         flood_permanent(y+1,x+1);
  1735.         flood_permanent(y-1,x-1);
  1736.         flood_permanent(y-1,x+1);
  1737.         flood_permanent(y+1,x-1);
  1738.     }
  1739.     }
  1740. }
  1741.  
  1742. static void
  1743. flood_permanent_dark(y,x)
  1744. int y,x;
  1745. {
  1746.     register cave_type *c_ptr;
  1747.     c_ptr = &cave[y][x];
  1748.     if (c_ptr->tl) {
  1749.     c_ptr->tl = FALSE;
  1750.     if (c_ptr->fval==NT_LIGHT_FLOOR)
  1751.         c_ptr->fval=NT_DARK_FLOOR;
  1752.     else if (c_ptr->fval==LIGHT_FLOOR)
  1753.         c_ptr->fval=DARK_FLOOR;
  1754. #ifdef MSDOS
  1755.     if (panel_contains(y,x)) {
  1756.         if (c_ptr->fval < MIN_CLOSED_SPACE){
  1757.         c_ptr->pl = FALSE;
  1758.         flood_permanent_dark(y+1,x);
  1759.         flood_permanent_dark(y-1,x);
  1760.         flood_permanent_dark(y,x+1);
  1761.         flood_permanent_dark(y,x-1);
  1762.         flood_permanent_dark(y+1,x+1);
  1763.         flood_permanent_dark(y-1,x-1);
  1764.         flood_permanent_dark(y-1,x+1);
  1765.         flood_permanent_dark(y+1,x-1);
  1766.         }
  1767.         lite_spot(y,x);
  1768.     }
  1769. #else
  1770.     if ((y-panel_row_prt)<23 && (y-panel_row_prt)>0 &&
  1771.         (x-panel_col_prt)>12 && (x-panel_col_prt)<80)
  1772.         if (c_ptr->fval<MIN_CLOSED_SPACE) {
  1773.         c_ptr->pl = FALSE;
  1774.         flood_permanent_dark(y+1,x);
  1775.         flood_permanent_dark(y-1,x);
  1776.         flood_permanent_dark(y,x+1);
  1777.         flood_permanent_dark(y,x-1);
  1778.         flood_permanent_dark(y+1,x+1);
  1779.         flood_permanent_dark(y-1,x-1);
  1780.         flood_permanent_dark(y-1,x+1);
  1781.         flood_permanent_dark(y+1,x-1);
  1782.         }
  1783.     print(loc_symbol(y, x), y, x);
  1784. #endif
  1785.     }
  1786. }
  1787.  
  1788. void 
  1789. light_room(y, x)
  1790.     int                 y, x;
  1791. {
  1792.     register cave_type *c_ptr;
  1793.     register monster_type  *m_ptr;
  1794.  
  1795.     c_ptr = &cave[y][x];
  1796.     if (!c_ptr->pl && c_ptr->lr) {
  1797.     c_ptr->pl = TRUE;
  1798.     m_ptr = &m_list[c_ptr->cptr];
  1799.  
  1800. /* Monsters that are intelligent wake up all the time; non-MINDLESS monsters wake
  1801.  * up 1/3 the time, and MINDLESS monsters wake up 1/10 the time -CWS
  1802.  */
  1803.     if ((c_list[m_ptr->mptr].cdefense & INTELLIGENT) ||
  1804.         (!(c_list[m_ptr->mptr].cdefense & MINDLESS) && (randint(3) == 1)) ||
  1805.         (randint(10) == 1))
  1806.         m_ptr->csleep = 0;
  1807.  
  1808.     if (c_ptr->fval == NT_DARK_FLOOR)
  1809.         c_ptr->fval = NT_LIGHT_FLOOR;
  1810.     else if (c_ptr->fval == DARK_FLOOR)
  1811.         c_ptr->fval = LIGHT_FLOOR;
  1812. #ifdef MSDOS
  1813.     lite_spot(y, x);       /* this does all that; plus color-safe -CFT */
  1814. #else
  1815.     if ((y - panel_row_prt) < 23 && (y - panel_row_prt) > 0 &&
  1816.         (x - panel_col_prt) > 12 && (x - panel_col_prt) < 80)
  1817.         print(loc_symbol(y, x), y, x);
  1818. #endif
  1819.     
  1820.     if (c_ptr->fval < MIN_CLOSED_SPACE) {
  1821.         c_ptr = &cave[y + 1][x];
  1822.         if ((!c_ptr->pl) && (c_ptr->lr))
  1823.         light_room(y + 1, x);
  1824.         
  1825.         c_ptr = &cave[y - 1][x];
  1826.         if ((!c_ptr->pl) && (c_ptr->lr))
  1827.         light_room(y - 1, x);
  1828.  
  1829.         c_ptr = &cave[y][x + 1];
  1830.         if ((!c_ptr->pl) && (c_ptr->lr))
  1831.         light_room(y, x + 1);
  1832.         
  1833.         c_ptr = &cave[y][x - 1];
  1834.         if ((!c_ptr->pl) && (c_ptr->lr))
  1835.         light_room(y, x - 1);
  1836.         
  1837.         c_ptr = &cave[y + 1][x + 1];
  1838.         if ((!c_ptr->pl) && (c_ptr->lr))
  1839.         light_room(y + 1, x + 1);
  1840.         
  1841.         c_ptr = &cave[y - 1][x - 1];
  1842.         if ((!c_ptr->pl) && (c_ptr->lr))
  1843.         light_room(y - 1, x - 1);
  1844.         
  1845.         c_ptr = &cave[y - 1][x + 1];
  1846.         if ((!c_ptr->pl) && (c_ptr->lr))
  1847.         light_room(y - 1, x + 1);
  1848.         
  1849.         c_ptr = &cave[y + 1][x - 1];
  1850.         if ((!c_ptr->pl) && (c_ptr->lr))
  1851.         light_room(y + 1, x - 1);
  1852.     }
  1853.     }     
  1854. }
  1855.  
  1856. void 
  1857. darken_room(y, x)
  1858.     int                 y, x;
  1859. {
  1860.     register cave_type *c_ptr;
  1861.  
  1862.     c_ptr = &cave[y][x];
  1863.     if (c_ptr->pl && c_ptr->lr) {
  1864.     c_ptr->tl = FALSE;
  1865.     if (c_ptr->fval == NT_LIGHT_FLOOR)
  1866.         c_ptr->fval = NT_DARK_FLOOR;
  1867.     else if (c_ptr->fval == LIGHT_FLOOR)
  1868.         c_ptr->fval = DARK_FLOOR;
  1869. #ifdef MSDOS
  1870.     if (panel_contains(y, x))
  1871.         if (c_ptr->fval < MIN_CLOSED_SPACE) {
  1872. #else
  1873.     if ((y - panel_row_prt) < 23 && (y - panel_row_prt) > 0 &&
  1874.         (x - panel_col_prt) > 12 && (x - panel_col_prt) < 80)
  1875.         if (c_ptr->fval < MIN_CLOSED_SPACE) {
  1876. #endif
  1877.         c_ptr->pl = FALSE;
  1878.         darken_room(y + 1, x);
  1879.         darken_room(y - 1, x);
  1880.         darken_room(y, x + 1);
  1881.         darken_room(y, x - 1);
  1882.         darken_room(y + 1, x + 1);
  1883.         darken_room(y - 1, x - 1);
  1884.         darken_room(y - 1, x + 1);
  1885.         darken_room(y + 1, x - 1);
  1886.         }
  1887.     print(loc_symbol(y, x), y, x);
  1888.     }
  1889. }
  1890.  
  1891. /* Lights up given location                -RAK-     */
  1892. void 
  1893. lite_spot(y, x)
  1894.     register int        y, x;
  1895. {
  1896.     if (panel_contains(y, x))
  1897.     print(loc_symbol(y, x), y, x);
  1898. }
  1899.  
  1900. /* Normal movement                     */
  1901. /* When FIND_FLAG,  light only permanent features     */
  1902. static void 
  1903. sub1_move_light(y1, x1, y2, x2)
  1904. register int x1, x2;
  1905. int y1, y2;
  1906. {
  1907.     register int        i, j;
  1908.     register cave_type *c_ptr;
  1909.     int                 tval, top, left, bottom, right;
  1910.     int          min_i, max_i, min_j, max_j;
  1911.  
  1912.     if (light_flag) {
  1913.     darken_player(y1, x1);
  1914.     if (find_flag && !find_prself)
  1915.         light_flag = FALSE;
  1916.     } else if (!find_flag || find_prself)
  1917.     light_flag = TRUE;
  1918.  
  1919. /* replace a check for in_bounds2 every loop with 4 quick computations -CWS */
  1920.     min_i = MY_MAX(0, (y2 - light_rad));
  1921.     max_i = MY_MIN(cur_height, (y2 + light_rad));
  1922.     min_j = MY_MAX(0, (x2 - light_rad));
  1923.     max_j = MY_MIN(cur_width, (x2 + light_rad));
  1924.     for (i = min_i; i <= max_i; i++)
  1925.     for (j = min_j; j <= max_j; j++)
  1926.         if (los(y2, x2, i, j) && distance(i, j, y2, x2) <= light_rad) {
  1927.         c_ptr = &cave[i][j];
  1928.         /* only light up if normal movement */
  1929.         if (light_flag)
  1930.             c_ptr->tl = TRUE;
  1931.         if (c_ptr->fval >= MIN_CAVE_WALL)
  1932.             c_ptr->pl = TRUE;
  1933.         else if (!c_ptr->fm && c_ptr->tptr != 0) {
  1934.             tval = t_list[c_ptr->tptr].tval;
  1935.             if ((tval >= TV_MIN_VISIBLE) && (tval <= TV_MAX_VISIBLE))
  1936.             c_ptr->fm = TRUE;
  1937.         }
  1938.         }
  1939. /* From uppermost to bottom most lines player was on.     */
  1940.     if (y1 < y2) {
  1941.     top = y1 - light_rad;
  1942.     bottom = y2 + light_rad;
  1943.     } else {
  1944.     top = y2 - light_rad;
  1945.     bottom = y1 + light_rad;
  1946.     }
  1947.     if (x1 < x2) {
  1948.     left = x1 - light_rad;
  1949.     right = x2 + light_rad;
  1950.     } else {
  1951.     left = x2 - light_rad;
  1952.     right = x1 + light_rad;
  1953.     }
  1954.     for (i = top; i <= bottom; i++)
  1955.     for (j = left; j <= right; j++)    /* Leftmost to rightmost do */
  1956.         lite_spot(i, j);       /* this does that, plus panel check +
  1957.                     * color safe */
  1958. }
  1959.  
  1960.  
  1961. /* When blinded,  move only the player symbol.         */
  1962. /* With no light,  movement becomes involved.         */
  1963. static void 
  1964. sub3_move_light(y1, x1, y2, x2)
  1965. register int y1, x1;
  1966. int y2, x2;
  1967. {
  1968.     if (light_flag) {
  1969.     darken_player(y1, x1);
  1970.     light_flag = FALSE;
  1971.     } else if (!find_flag || find_prself)    /* um55 change -CFT */
  1972.     lite_spot(y1, x1);
  1973.  
  1974. #ifdef TC_COLOR
  1975.     if (!no_color_flag)
  1976.     textcolor(LIGHTGRAY);
  1977. #endif
  1978.  
  1979.     if (!find_flag || find_prself)
  1980.     print('@', y2, x2);
  1981. }
  1982.  
  1983. void
  1984. darken_player(y1, x1)
  1985. int y1, x1;
  1986. {
  1987.     int min_i, max_i, min_j, max_j, rad, i, j;
  1988.  
  1989.     rad = MY_MAX(light_rad, old_rad);
  1990.  
  1991. /* replace a check for in_bounds2 every loop with 4 quick computations -CWS */
  1992.     min_i = MY_MAX(0, (y1 - rad));
  1993.     max_i = MY_MIN(cur_height, (y1 + rad));
  1994.     min_j = MY_MAX(0, (x1 - rad));
  1995.     max_j = MY_MIN(cur_width, (x1 + rad));
  1996.  
  1997.     for (i = min_i; i <= max_i; i++)
  1998.         for (j = min_j; j <= max_j; j++) {
  1999.         cave[i][j].tl = FALSE;  /* Turn off light */
  2000.         lite_spot(i, j);
  2001.         }
  2002. }
  2003.  
  2004. /* Package for moving the character's light about the screen     */
  2005. /* Four cases : Normal, Finding, Blind, and Nolight     -RAK-     */
  2006. void 
  2007. move_light(y1, x1, y2, x2)
  2008. int y1, x1, y2, x2;
  2009. {
  2010.     if (py.flags.blind > 0 || !player_light)
  2011.     sub3_move_light(y1, x1, y2, x2);
  2012.     else
  2013.     sub1_move_light(y1, x1, y2, x2);
  2014. }
  2015.  
  2016.  
  2017. /*
  2018.  * Something happens to disturb the player.        -CJS- The first arg
  2019.  * indicates a major disturbance, which affects search. The second arg
  2020.  * indicates a light change. 
  2021.  */
  2022. void 
  2023. disturb(s, l)
  2024. int s, l;
  2025. {
  2026.     command_count = 0;
  2027.     if (s && (py.flags.status & PY_SEARCH))
  2028.     search_off();
  2029.     if (py.flags.rest != 0)
  2030.     rest_off();
  2031.     if (l || find_flag) {
  2032.     find_flag = FALSE;
  2033.     check_view();
  2034.     }
  2035.     flush();
  2036. }
  2037.  
  2038.  
  2039. /* Search Mode enhancement                -RAK-     */
  2040. void 
  2041. search_on()
  2042. {
  2043.     change_speed(1);
  2044.     py.flags.status |= PY_SEARCH;
  2045.     prt_state();
  2046.     prt_speed();
  2047.     py.flags.food_digested++;
  2048. }
  2049.  
  2050. void 
  2051. search_off()
  2052. {
  2053.     check_view();
  2054.     change_speed(-1);
  2055.     py.flags.status &= ~PY_SEARCH;
  2056.     prt_state();
  2057.     prt_speed();
  2058.     py.flags.food_digested--;
  2059. }
  2060.  
  2061.  
  2062. /* Resting allows a player to safely restore his hp    -RAK-     */
  2063. void 
  2064. rest()
  2065. {
  2066.     int   rest_num;
  2067.     vtype rest_str;
  2068.  
  2069.     if (command_count > 0) {
  2070.     rest_num = command_count;
  2071.     command_count = 0;
  2072.     } else {
  2073.     char                ch;
  2074.  
  2075.     prt("Rest for how long? ('*' for HP/mana; '&' as needed) : ", 0, 0);
  2076.     rest_num = 0;
  2077.     if (get_string(rest_str, 0, 54, 5)) {
  2078.         if (sscanf(rest_str, "%c", &ch) == 1)
  2079.         if (ch == '*')
  2080.             rest_num = (-1);
  2081.         else if (ch == '&')
  2082.             rest_num = (-2);
  2083.         else {
  2084.             if (atoi(rest_str) > 30000)
  2085.             rest_num = 30000;
  2086.             else
  2087.             rest_num = atoi(rest_str);
  2088.         }
  2089.     }
  2090.     }
  2091.     if (rest_num != 0) {
  2092.     if (py.flags.status & PY_SEARCH)
  2093.         search_off();
  2094.     py.flags.rest = rest_num;
  2095.     py.flags.status |= PY_REST;
  2096.     prt_state();
  2097.     py.flags.food_digested--;
  2098.     prt("Press any key to stop resting...", 0, 0);
  2099.     put_qio();
  2100.     } else {
  2101.     erase_line(MSG_LINE, 0);
  2102.     free_turn_flag = TRUE;
  2103.     }
  2104. }
  2105.  
  2106.  
  2107. void 
  2108. rest_off()
  2109. {
  2110.     py.flags.rest = 0;
  2111.     py.flags.status &= ~PY_REST;
  2112.     prt_state();
  2113.     msg_print(NULL);           /* flush last message, or delete "press
  2114.                     * any key" message */
  2115.     py.flags.food_digested++;
  2116. }
  2117.  
  2118.  
  2119. /* Attacker's level and plusses,  defender's AC        -RAK-     */
  2120. int 
  2121. test_hit(bth, level, pth, ac, attack_type)
  2122. int bth, level, pth, ac, attack_type;
  2123. {
  2124.     register int i, die;
  2125.  
  2126.     disturb(1, 0);
  2127.     i = bth + pth * BTH_PLUS_ADJ
  2128.     + (level * class_level_adj[py.misc.pclass][attack_type]);
  2129. /* pth could be less than 0 if player wielding weapon too heavy for him */
  2130. /* always miss 1 out of 20, always hit 1 out of 20 */
  2131.     die = randint(20);
  2132.     if ((die != 1) && ((die == 20)
  2133.                || ((i > 0) && (randint(i) > ((3 * ac) / 4)))))
  2134.     return TRUE;
  2135.     else
  2136.     return FALSE;
  2137. }
  2138.  
  2139.  
  2140. /* Decreases players hit points and sets death flag if necessary */
  2141. /* -RAK-     */
  2142. void 
  2143. take_hit(damage, hit_from)
  2144. int damage;
  2145. const char *hit_from;
  2146. {
  2147.     if (py.flags.invuln > 0 && damage < 9000)
  2148.     damage = 0;
  2149.     py.misc.chp -= damage;
  2150.     if (py.misc.chp < 0) {
  2151.     if ((wizard) && !(get_Yn("Die?"))) {
  2152.         py.misc.chp=py.misc.mhp;
  2153.         death=FALSE;
  2154.         prt_chp();
  2155.         msg_print("OK, so you don't die.");
  2156.     } else {        
  2157.         if (!death) {
  2158.         death = TRUE;
  2159.         (void)strcpy(died_from, hit_from);
  2160.         total_winner = FALSE;
  2161.         }
  2162.         new_level_flag = TRUE;
  2163.     }
  2164.     } else
  2165.     prt_chp();
  2166.     if (py.misc.chp <= py.misc.mhp * hitpoint_warn / 10) {
  2167.     msg_print("*** LOW HITPOINT WARNING! ***");
  2168.     msg_print(NULL);    /* make sure they see it -CWS */
  2169.     }
  2170. }
  2171.  
  2172.     
  2173. /* Change a trap from invisible to visible        -RAK-     */
  2174. /* Note: Secret doors are handled here                 */
  2175. void 
  2176. change_trap(y, x)
  2177. register int y, x;
  2178. {
  2179.     register cave_type  *c_ptr;
  2180.     register inven_type *t_ptr;
  2181.  
  2182.     c_ptr = &cave[y][x];
  2183.     t_ptr = &t_list[c_ptr->tptr];
  2184.     if (t_ptr->tval == TV_INVIS_TRAP) {
  2185.     t_ptr->tval = TV_VIS_TRAP;
  2186.     lite_spot(y, x);
  2187.     } else if (t_ptr->tval == TV_SECRET_DOOR) {
  2188.     /* change secret door to closed door */
  2189.     t_ptr->index = OBJ_CLOSED_DOOR;
  2190.     t_ptr->tval = object_list[OBJ_CLOSED_DOOR].tval;
  2191.     t_ptr->tchar = object_list[OBJ_CLOSED_DOOR].tchar;
  2192.     lite_spot(y, x);
  2193.     }
  2194. }
  2195.  
  2196.  
  2197. /* Searches for hidden things.            -RAK-     */
  2198. void 
  2199. search(y, x, chance)
  2200. int y, x, chance;
  2201. {
  2202.     register int           i, j;
  2203.     register cave_type    *c_ptr;
  2204.     register inven_type   *t_ptr;
  2205.     register struct flags *p_ptr;
  2206.     bigvtype               tmp_str, tmp_str2;
  2207.  
  2208.     p_ptr = &py.flags;
  2209.     if (p_ptr->confused > 0)
  2210.     chance = chance / 10;
  2211.     if ((p_ptr->blind > 0) || no_light())
  2212.     chance = chance / 10;
  2213.     if (p_ptr->image > 0)
  2214.     chance = chance / 10;
  2215.     for (i = (y - 1); i <= (y + 1); i++)
  2216.     for (j = (x - 1); j <= (x + 1); j++)
  2217.         if (randint(100) < chance) {    /* always in_bounds here */
  2218.         c_ptr = &cave[i][j];
  2219.         /* Search for hidden objects           */
  2220.         if (c_ptr->tptr != 0) {
  2221.             t_ptr = &t_list[c_ptr->tptr];
  2222.         /* Trap on floor?               */
  2223.             if (t_ptr->tval == TV_INVIS_TRAP) {
  2224.             objdes(tmp_str2, t_ptr, TRUE);
  2225.             (void)sprintf(tmp_str, "You have found %s.", tmp_str2);
  2226.             msg_print(tmp_str);
  2227.             change_trap(i, j);
  2228.             end_find();
  2229.             }
  2230.         /* Secret door?               */
  2231.             else if (t_ptr->tval == TV_SECRET_DOOR) {
  2232.             msg_print("You have found a secret door.");
  2233.             change_trap(i, j);
  2234.             end_find();
  2235.             }
  2236.         /* Chest is trapped?           */
  2237.             else if (t_ptr->tval == TV_CHEST) {
  2238.             /* mask out the treasure bits */
  2239.             if ((t_ptr->flags & CH_TRAPPED) > 1)
  2240.                 if (!known2_p(t_ptr)) {
  2241.                 known2(t_ptr);
  2242.                 msg_print("You have discovered a trap on the chest!");
  2243.                 } else
  2244.                 msg_print("The chest is trapped!");
  2245.             }
  2246.         }
  2247.         }
  2248. }
  2249.  
  2250.  
  2251. /* The running algorithm:            -CJS-
  2252.  
  2253.    Overview: You keep moving until something interesting happens.
  2254.    If you are in an enclosed space, you follow corners. This is
  2255.    the usual corridor scheme. If you are in an open space, you go
  2256.    straight, but stop before entering enclosed space. This is
  2257.    analogous to reaching doorways. If you have enclosed space on
  2258.    one side only (that is, running along side a wall) stop if
  2259.    your wall opens out, or your open space closes in. Either case
  2260.    corresponds to a doorway.
  2261.  
  2262.    What happens depends on what you can really SEE. (i.e. if you
  2263.    have no light, then running along a dark corridor is JUST like
  2264.    running in a dark room.) The algorithm works equally well in
  2265.    corridors, rooms, mine tailings, earthquake rubble, etc, etc.
  2266.  
  2267.    These conditions are kept in static memory:
  2268.     find_openarea     You are in the open on at least one
  2269.              side.
  2270.     find_breakleft     You have a wall on the left, and will
  2271.              stop if it opens
  2272.     find_breakright     You have a wall on the right, and will
  2273.              stop if it opens
  2274.  
  2275.    To initialize these conditions is the task of find_init. If
  2276.    moving from the square marked @ to the square marked . (in the
  2277.    two diagrams below), then two adjacent sqares on the left and
  2278.    the right (L and R) are considered. If either one is seen to
  2279.    be closed, then that side is considered to be closed. If both
  2280.    sides are closed, then it is an enclosed (corridor) run.
  2281.  
  2282.      LL        L
  2283.     @.           L.R
  2284.      RR           @R
  2285.  
  2286.    Looking at more than just the immediate squares is
  2287.    significant. Consider the following case. A run along the
  2288.    corridor will stop just before entering the center point,
  2289.    because a choice is clearly established. Running in any of
  2290.    three available directions will be defined as a corridor run.
  2291.    Note that a minor hack is inserted to make the angled corridor
  2292.    entry (with one side blocked near and the other side blocked
  2293.    further away from the runner) work correctly. The runner moves
  2294.    diagonally, but then saves the previous direction as being
  2295.    straight into the gap. Otherwise, the tail end of the other
  2296.    entry would be perceived as an alternative on the next move.
  2297.  
  2298.        #.#
  2299.       ##.##
  2300.       .@...
  2301.       ##.##
  2302.        #.#
  2303.  
  2304.    Likewise, a run along a wall, and then into a doorway (two
  2305.    runs) will work correctly. A single run rightwards from @ will
  2306.    stop at 1. Another run right and down will enter the corridor
  2307.    and make the corner, stopping at the 2.
  2308.  
  2309.     #@      1
  2310.     ########### ######
  2311.     2        #
  2312.     #############
  2313.     #
  2314.  
  2315.    After any move, the function area_affect is called to
  2316.    determine the new surroundings, and the direction of
  2317.    subsequent moves. It takes a location (at which the runner has
  2318.    just arrived) and the previous direction (from which the
  2319.    runner is considered to have come). Moving one square in some
  2320.    direction places you adjacent to three or five new squares
  2321.    (for straight and diagonal moves) to which you were not
  2322.    previously adjacent.
  2323.  
  2324.        ...!      ...           EG Moving from 1 to 2.
  2325.        .12!      .1.!          . means previously adjacent
  2326.        ...!      ..2!          ! means newly adjacent
  2327.            !!!
  2328.  
  2329.    You STOP if you can't even make the move in the chosen
  2330.    direction. You STOP if any of the new squares are interesting
  2331.    in any way: usually containing monsters or treasure. You STOP
  2332.    if any of the newly adjacent squares seem to be open, and you
  2333.    are also looking for a break on that side. (i.e. find_openarea
  2334.    AND find_break) You STOP if any of the newly adjacent squares
  2335.    do NOT seem to be open and you are in an open area, and that
  2336.    side was previously entirely open.
  2337.  
  2338.    Corners: If you are not in the open (i.e. you are in a
  2339.    corridor) and there is only one way to go in the new squares,
  2340.    then turn in that direction. If there are more than two new
  2341.    ways to go, STOP. If there are two ways to go, and those ways
  2342.    are separated by a square which does not seem to be open, then
  2343.    STOP.
  2344.  
  2345.    Otherwise, we have a potential corner. There are two new open
  2346.    squares, which are also adjacent. One of the new squares is
  2347.    diagonally located, the other is straight on (as in the
  2348.    diagram). We consider two more squares further out (marked
  2349.    below as ?).
  2350.       .X
  2351.      @.?
  2352.       #?
  2353.    If they are both seen to be closed, then it is seen that no
  2354.    benefit is gained from moving straight. It is a known corner.
  2355.    To cut the corner, go diagonally, otherwise go straight, but
  2356.    pretend you stepped diagonally into that next location for a
  2357.    full view next time. Conversely, if one of the ? squares is
  2358.    not seen to be closed, then there is a potential choice. We check
  2359.    to see whether it is a potential corner or an intersection/room entrance.
  2360.    If the square two spaces straight ahead, and the space marked with 'X'
  2361.    are both blank, then it is a potential corner and enter if find_examine
  2362.    is set, otherwise must stop because it is not a corner. */
  2363.  
  2364. /*
  2365.  * The cycle lists the directions in anticlockwise order, for    -CJS- over
  2366.  * two complete cycles. The chome array maps a direction on to its position
  2367.  * in the cycle. 
  2368.  */
  2369. static int cycle[] = {1, 2, 3, 6, 9, 8, 7, 4, 1, 2, 3, 6, 9, 8, 7, 4, 1};
  2370. static int chome[] = {-1, 8, 9, 10, 7, -1, 11, 6, 5, 4};
  2371. static int find_openarea, find_breakright, find_breakleft, find_prevdir;
  2372. static int find_direction;/* Keep a record of which way we are going. */
  2373.  
  2374. void 
  2375. find_init(dir)
  2376. int dir;
  2377. {
  2378.     int          row, col, deepleft, deepright;
  2379.     register int i, shortleft, shortright;
  2380.  
  2381.     darken_player(char_row, char_col);
  2382.     old_rad = light_rad;
  2383.     if (light_rad >= 0)
  2384.     light_rad = 1;
  2385.  
  2386.     row = char_row;
  2387.     col = char_col;
  2388.     if (!mmove(dir, &row, &col))
  2389.     find_flag = FALSE;
  2390.     else {
  2391.     find_direction = dir;
  2392.     find_flag = 1;
  2393.     find_breakright = find_breakleft = FALSE;
  2394.     find_prevdir = dir;
  2395.     if (py.flags.blind < 1) {
  2396.         i = chome[dir];
  2397.         deepleft = deepright = FALSE;
  2398.         shortright = shortleft = FALSE;
  2399.         if (see_wall(cycle[i + 1], char_row, char_col)) {
  2400.         find_breakleft = TRUE;
  2401.         shortleft = TRUE;
  2402.         } else if (see_wall(cycle[i + 1], row, col)) {
  2403.         find_breakleft = TRUE;
  2404.         deepleft = TRUE;
  2405.         }
  2406.         if (see_wall(cycle[i - 1], char_row, char_col)) {
  2407.         find_breakright = TRUE;
  2408.         shortright = TRUE;
  2409.         } else if (see_wall(cycle[i - 1], row, col)) {
  2410.         find_breakright = TRUE;
  2411.         deepright = TRUE;
  2412.         }
  2413.         if (find_breakleft && find_breakright) {
  2414.         find_openarea = FALSE;
  2415.         if (dir & 1) {       /* a hack to allow angled corridor entry */
  2416.             if (deepleft && !deepright)
  2417.             find_prevdir = cycle[i - 1];
  2418.             else if (deepright && !deepleft)
  2419.             find_prevdir = cycle[i + 1];
  2420.         }
  2421.         /* else if there is a wall two spaces ahead and seem to be in a
  2422.          * corridor, then force a turn into the side corridor, must be
  2423.          * moving straight into a corridor here 
  2424.          */
  2425.         else if (see_wall(cycle[i], row, col)) {
  2426.             if (shortleft && !shortright)
  2427.             find_prevdir = cycle[i - 2];
  2428.             else if (shortright && !shortleft)
  2429.             find_prevdir = cycle[i + 2];
  2430.         }
  2431.         } else
  2432.         find_openarea = TRUE;
  2433.     }
  2434.     }
  2435.  
  2436. /*
  2437.  * We must erase the player symbol '@' here, because sub3_move_light() does
  2438.  * not erase the previous location of the player when in find mode and when
  2439.  * find_prself is FALSE.  The player symbol is not draw at all in this case
  2440.  * while moving, so the only problem is on the first turn of find mode, when
  2441.  * the initial position of the character must be erased. Hence we must do the
  2442.  * erasure here.  
  2443.  */
  2444.     if (!light_flag && !find_prself)
  2445. #ifdef TC_COLOR
  2446.     lite_spot(char_row, char_col);
  2447. #else
  2448.     print(loc_symbol(char_row, char_col), char_row, char_col);
  2449. #endif
  2450.  
  2451.     move_char(dir, TRUE);
  2452.     if (find_flag == FALSE)
  2453.     command_count = 0;
  2454. }
  2455.  
  2456. void 
  2457. find_run()
  2458. {
  2459. /* prevent infinite loops in find mode, will stop after moving 100 times */
  2460.     if (find_flag++ > 100) {
  2461.     msg_print("You stop running to catch your breath.");
  2462.     end_find();
  2463.     } else
  2464.     move_char(find_direction, TRUE);
  2465. }
  2466.  
  2467. /* Switch off the run flag - and get the light correct. -CJS- */
  2468. void 
  2469. end_find()
  2470. {
  2471.     if (find_flag) {
  2472.     find_flag = FALSE;
  2473.     light_rad = old_rad;
  2474.     move_light(char_row, char_col, char_row, char_col);
  2475.     }
  2476. }
  2477.  
  2478. /* Do we see a wall? Used in running.        -CJS- */
  2479. static int 
  2480. see_wall(dir, y, x)
  2481. int dir, y, x;
  2482. {
  2483.     char c;
  2484.  
  2485.     if (!mmove(dir, &y, &x))       /* check to see if movement there possible */
  2486.     return TRUE;
  2487. #ifdef MSDOS
  2488.     else if ((c = loc_symbol(y, x)) == wallsym || c == '%')
  2489. #else
  2490. #ifdef ATARIST_MWC
  2491.     else if ((c = loc_symbol(y, x)) == (unsigned char)240 || c == '%')
  2492. #else
  2493.     else if ((c = loc_symbol(y, x)) == '#' || c == '%')
  2494. #endif
  2495. #endif
  2496.     return TRUE;
  2497.     else
  2498.     return FALSE;
  2499. }
  2500.  
  2501. /* Do we see anything? Used in running.        -CJS- */
  2502. static int 
  2503. see_nothing(dir, y, x)
  2504.     int                 dir, y, x;
  2505. {
  2506.     if (!mmove(dir, &y, &x))       /* check to see if movement there possible */
  2507.     return FALSE;
  2508.     else if (loc_symbol(y, x) == ' ')
  2509.     return TRUE;
  2510.     else
  2511.     return FALSE;
  2512. }
  2513.  
  2514.  
  2515. /* Determine the next direction for a run, or if we should stop.  -CJS- */
  2516. void 
  2517. area_affect(dir, y, x)
  2518. int dir, y, x;
  2519. {
  2520.     int                  newdir = 0, t, inv, check_dir = 0, row, col;
  2521.     register int         i, max, option, option2;
  2522.     register cave_type *c_ptr;
  2523.  
  2524.     if (py.flags.blind < 1) {
  2525.     option = 0;
  2526.     option2 = 0;
  2527.     dir = find_prevdir;
  2528.     max = (dir & 1) + 1;
  2529.     /* Look at every newly adjacent square. */
  2530.     for (i = -max; i <= max; i++) {
  2531.         newdir = cycle[chome[dir] + i];
  2532.         row = y;
  2533.         col = x;
  2534.         if (mmove(newdir, &row, &col)) {
  2535.         /* Objects player can see (Including doors?) cause a stop. */
  2536.         c_ptr = &cave[row][col];
  2537.         if (player_light || c_ptr->tl || c_ptr->pl || c_ptr->fm) {
  2538.             if (c_ptr->tptr != 0) {
  2539.             t = t_list[c_ptr->tptr].tval;
  2540.             if (t != TV_INVIS_TRAP && t != TV_SECRET_DOOR
  2541.                 && (t != TV_OPEN_DOOR || !find_ignore_doors)) {
  2542.                 end_find();
  2543.                 return;
  2544.             }
  2545.             }
  2546.         /* Also Creatures         */
  2547.         /* the monster should be visible since update_mon() checks
  2548.          * for the special case of being in find mode 
  2549.          */
  2550.             if (c_ptr->cptr > 1 && m_list[c_ptr->cptr].ml) {
  2551.             end_find();
  2552.             return;
  2553.             }
  2554.             inv = FALSE;
  2555.         } else
  2556.             inv = TRUE;        /* Square unseen. Treat as open. */
  2557.  
  2558.         if (c_ptr->fval <= MAX_OPEN_SPACE || inv) {
  2559.             if (find_openarea) {
  2560.             if (i < 0) {
  2561.                 if (find_breakright) {
  2562.                 end_find();
  2563.                 return;
  2564.                 }
  2565.             } else if (i > 0) {
  2566.                 if (find_breakleft) {
  2567.                 end_find();
  2568.                 return;
  2569.                 }
  2570.             }
  2571.             } else if (option == 0)
  2572.             option = newdir;    /* The first new direction. */
  2573.             else if (option2 != 0) {
  2574.             end_find();             /* Three new directions. STOP. */
  2575.             return;
  2576.             } else if (option != cycle[chome[dir] + i - 1]) {
  2577.             end_find();/* If not adjacent to prev, STOP */
  2578.             return;
  2579.             } else {
  2580.             /* Two adjacent choices. Make option2 the diagonal, and
  2581.              * remember the other diagonal adjacent to the first
  2582.              * option. 
  2583.              */
  2584.             if ((newdir & 1) == 1) {
  2585.                 check_dir = cycle[chome[dir] + i - 2];
  2586.                 option2 = newdir;
  2587.             } else {
  2588.                 check_dir = cycle[chome[dir] + i + 1];
  2589.                 option2 = option;
  2590.                 option = newdir;
  2591.             }
  2592.             }
  2593.         } else if (find_openarea) {
  2594.         /* We see an obstacle. In open area, STOP if on a side previously open. */
  2595.             if (i < 0) {
  2596.             if (find_breakleft) {
  2597.                 end_find();
  2598.                 return;
  2599.             }
  2600.             find_breakright = TRUE;
  2601.             } else if (i > 0) {
  2602.             if (find_breakright) {
  2603.                 end_find();
  2604.                 return;
  2605.             }
  2606.             find_breakleft = TRUE;
  2607.             }
  2608.         }
  2609.         }
  2610.     }
  2611.  
  2612.     if (find_openarea == FALSE) {    /* choose a direction. */
  2613.         if (option2 == 0 || (find_examine && !find_cut)) {
  2614.         /* There is only one option, or if two, then we always examine
  2615.          * potential corners and never cut known corners, so you step
  2616.          * into the straight option. 
  2617.          */
  2618.         if (option != 0)
  2619.             find_direction = option;
  2620.         if (option2 == 0)
  2621.             find_prevdir = option;
  2622.         else
  2623.             find_prevdir = option2;
  2624.         } else {
  2625.         /* Two options! */
  2626.         row = y;
  2627.         col = x;
  2628.         (void)mmove(option, &row, &col);
  2629.         if (!see_wall(option, row, col)
  2630.             || !see_wall(check_dir, row, col)) {
  2631.         /*
  2632.          * Don't see that it is closed off.  This could be a
  2633.          * potential corner or an intersection. 
  2634.          */
  2635.             if (find_examine && see_nothing(option, row, col)
  2636.             && see_nothing(option2, row, col))
  2637.             /*
  2638.              * Can not see anything ahead and in the direction we are
  2639.              * turning, assume that it is a potential corner. 
  2640.              */
  2641.             {
  2642.             find_direction = option;
  2643.             find_prevdir = option2;
  2644.             } else
  2645.             /* STOP: we are next to an intersection or a room */
  2646.             end_find();
  2647.         } else if (find_cut) {
  2648.         /* This corner is seen to be enclosed; we cut the corner. */
  2649.             find_direction = option2;
  2650.             find_prevdir = option2;
  2651.         } else {
  2652.         /*
  2653.          * This corner is seen to be enclosed, and we deliberately go
  2654.          * the long way. 
  2655.          */
  2656.             find_direction = option;
  2657.             find_prevdir = option2;
  2658.         }
  2659.         }
  2660.     }
  2661.     }
  2662. }
  2663.  
  2664.  
  2665. /* AC gets worse                    -RAK-     */
  2666. /* Note: This routine affects magical AC bonuses so that stores      */
  2667. /* can detect the damage.                     */
  2668. int 
  2669. minus_ac(typ_dam)
  2670. int32u typ_dam;
  2671. {
  2672.     register int         i, j;
  2673.     int                  tmp[6], minus, do_damage;
  2674.     register inven_type *i_ptr;
  2675.     bigvtype             out_val, tmp_str;
  2676.  
  2677.     i = 0;
  2678.     if (inventory[INVEN_BODY].tval != TV_NOTHING) {
  2679.     tmp[i] = INVEN_BODY;
  2680.     i++;
  2681.     }
  2682.     if (inventory[INVEN_ARM].tval != TV_NOTHING) {
  2683.     tmp[i] = INVEN_ARM;
  2684.     i++;
  2685.     }
  2686.     if (inventory[INVEN_OUTER].tval != TV_NOTHING) {
  2687.     tmp[i] = INVEN_OUTER;
  2688.     i++;
  2689.     }
  2690.     if (inventory[INVEN_HANDS].tval != TV_NOTHING) {
  2691.     tmp[i] = INVEN_HANDS;
  2692.     i++;
  2693.     }
  2694.     if (inventory[INVEN_HEAD].tval != TV_NOTHING) {
  2695.     tmp[i] = INVEN_HEAD;
  2696.     i++;
  2697.     }
  2698. /* also affect boots */
  2699.     if (inventory[INVEN_FEET].tval != TV_NOTHING) {
  2700.     tmp[i] = INVEN_FEET;
  2701.     i++;
  2702.     }
  2703.     minus = FALSE;
  2704.     if (i > 0) {
  2705.     j = tmp[randint(i) - 1];
  2706.     i_ptr = &inventory[j];
  2707.     switch (typ_dam) {
  2708.       case TR_RES_ACID:
  2709.         if ((i_ptr->flags & TR_RES_ACID) || (i_ptr->flags2 & TR_IM_ACID) ||
  2710.         ((i_ptr->flags2 & TR_ARTIFACT) && (randint(5)>2)))
  2711.         do_damage = FALSE;
  2712.         else
  2713.         do_damage = TRUE;
  2714.         break;
  2715.       default:           /* unknown damage type... */
  2716.         do_damage = FALSE;
  2717.     }
  2718.     if (do_damage == FALSE) {
  2719.         objdes(tmp_str, &inventory[j], FALSE);
  2720.         (void)sprintf(out_val, "Your %s resists damage!", tmp_str);
  2721.         msg_print(out_val);
  2722.         minus = FALSE;
  2723.     } else if ((i_ptr->ac + i_ptr->toac) > 0) {
  2724.         objdes(tmp_str, &inventory[j], FALSE);
  2725.         (void)sprintf(out_val, "Your %s is damaged!", tmp_str);
  2726.         msg_print(out_val);
  2727.         i_ptr->toac--;
  2728.         calc_bonuses();
  2729.         minus = TRUE;
  2730.     }
  2731.     }
  2732.     return (minus);
  2733. }
  2734.  
  2735.  
  2736. /* Corrode the unsuspecting person's armor         -RAK-     */
  2737. void 
  2738. corrode_gas(kb_str)
  2739. const char *kb_str;
  2740. {
  2741.     if (!py.flags.acid_im)
  2742.     if (!minus_ac((int32u) TR_RES_ACID))
  2743.         take_hit(randint(8), kb_str);
  2744.     inven_damage(set_corrodes, 5);
  2745. }
  2746.  
  2747.  
  2748. /* Poison gas the idiot.                -RAK-     */
  2749. void 
  2750. poison_gas(dam, kb_str)
  2751. int dam;
  2752. const char *kb_str;
  2753. {
  2754.     if (py.flags.resist_poison > 0)
  2755.     dam = 2 * dam / 3;
  2756.     if (py.flags.poison_resist)
  2757.     dam = (dam * 3) / 5;
  2758.     if (py.flags.poison_im)
  2759.     dam = 1;
  2760.     take_hit(dam, kb_str);
  2761.     if (!(py.flags.poison_resist || py.flags.resist_poison
  2762.       || py.flags.poison_im))
  2763.     py.flags.poisoned += 12 + randint(dam);
  2764. }
  2765.  
  2766.  
  2767. /* Burn the fool up.                    -RAK-     */
  2768. void 
  2769. fire_dam(dam, kb_str)
  2770. int dam;
  2771. const char *kb_str;
  2772. {
  2773.     if (py.flags.fire_resist)
  2774.     dam = dam / 3;
  2775.     if (py.flags.resist_heat > 0)
  2776.     dam = dam / 3;
  2777.     if (py.flags.fire_im)
  2778.     dam = 1;
  2779.     take_hit(dam, kb_str);
  2780.     inven_damage(set_flammable, 3);
  2781. }
  2782.  
  2783.  
  2784. /* Freeze him to death.                -RAK-     */
  2785. void 
  2786. cold_dam(dam, kb_str)
  2787. int dam;
  2788. const char *kb_str;
  2789. {
  2790.     if (py.flags.cold_resist)
  2791.     dam = dam / 3;
  2792.     if (py.flags.resist_cold > 0)
  2793.     dam = dam / 3;
  2794.     if (py.flags.cold_im)
  2795.     dam = 1;
  2796.     take_hit(dam, kb_str);
  2797.     inven_damage(set_frost_destroy, 5);
  2798. }
  2799.  
  2800.  
  2801. /* Lightning bolt the sucker away.            -RAK-     */
  2802. void 
  2803. light_dam(dam, kb_str)
  2804. int dam;
  2805. const char *kb_str;
  2806. {
  2807.     if (py.flags.resist_light)
  2808.     dam = dam / 3;
  2809.     if (py.flags.lght_resist)
  2810.     dam = dam / 3;
  2811.     if (py.flags.light_im)
  2812.     dam = 1;
  2813.     take_hit(dam, kb_str);
  2814.     inven_damage(set_lightning_destroy, 3);
  2815. }
  2816.  
  2817.  
  2818. /* Throw acid on the hapless victim            -RAK-     */
  2819. void 
  2820. acid_dam(dam, kb_str)
  2821. int dam;
  2822. const char *kb_str;
  2823. {
  2824.     register int flag;
  2825.  
  2826.     if (py.flags.acid_resist > 0)
  2827.     dam = dam / 3;
  2828.     if (py.flags.resist_acid > 0)
  2829.     dam = dam / 3;
  2830.     if (py.flags.acid_im)
  2831.     dam = 1;
  2832.     flag = 0;
  2833.     if (!py.flags.resist_acid)
  2834.     if (minus_ac((int32u) TR_RES_ACID))
  2835.         flag = 1;
  2836.     if (py.flags.acid_resist)
  2837.     flag += 2;
  2838.     inven_damage(set_acid_affect, 3);
  2839. }
  2840.